diff --git a/.circleci/config.yml b/.circleci/config.yml index bc4b58c631..58256e0dd9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,114 +1,215 @@ -# Javascript Node CircleCI 2.0 configuration file -# Check https://circleci.com/docs/2.0/language-javascript/ for more details -version: 2 -jobs: - common: - working_directory: ~/typeorm - docker: - - image: circleci/node:10.16.0 - - image: mysql:5.7.24 - environment: - MYSQL_ROOT_PASSWORD: "admin" - MYSQL_DATABASE: "test" - - image: mariadb:10.1.37 - name: mariadb - environment: - MYSQL_ROOT_PASSWORD: "admin" - MYSQL_DATABASE: "test" - - image: circleci/postgres:9.6.11-postgis - environment: - POSTGRES_USER: "test" - POSTGRES_PASSWORD: "test" - POSTGRES_DB: "test" - - image: circleci/mongo:3.4.18 - # - image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu - # environment: - # SA_PASSWORD: "Admin12345" - # ACCEPT_EULA: "Y" +version: 2.1 +orbs: + codecov: codecov/codecov@1.1.1 + +commands: + create-typeorm-config: + parameters: + databases: + type: string + default: "" + steps: + - when: + condition: + equal: [ << parameters.databases >>, "" ] + steps: + - run: + name: "Enabling Databases in ORM config" + command: cp ormconfig.circleci-common.json ./ormconfig.json + - unless: + condition: + equal: [ << parameters.databases >>, "" ] + steps: + - run: + name: "Enabling Databases in ORM config" + command: > + cat ormconfig.circleci-common.json \ + | jq 'map(.skip = if (.name | IN($ARGS.positional[])) then false else true end)' --args << parameters.databases >> \ + > ormconfig.json + - run: + name: Check ORMConfig + command: cat ormconfig.json + + install-packages: + parameters: + cache-key: + type: string + default: "" steps: - - checkout - - run: cp ormconfig.circleci-common.json ormconfig.json - # Download and cache dependencies - restore_cache: - keys: - - v1-dependencies-{{ checksum "package.json" }} - # fallback to using the latest cache if no exact match is found - - v1-dependencies- - - run: npm install + name: Restore node_modules cache + key: node_modules-<< parameters.cache-key >>-{{ checksum "package-lock.json" }} + - run: + name: Verify `package.json` and `package-lock.json` are in sync + command: npx lock-verify + - run: + # This uses `npm install` instead of `npm ci` + # because of https://github.com/npm/cli/issues/558 + name: Install Node Packages + command: | + if [ ! -d node_modules ]; then + npm install + fi + - run: + # This is pretty terrible but OracleDB requires you to grab the binaries OOB + # from the normal installation, place them in the LD Path + # also - not super well documented - grab `libaio` as well + # Because this is technically the same image as the runner we'll snag + # the libaio1 and place them in the same instantclient directory. + name: Download Required OracleDB Binaries + command: | + if [ ! -d node_modules/oracledb/instantclient_19_8 ]; then + curl -sf -o node_modules/oracledb/instantclient.zip $BLOB_URL + unzip -qqo node_modules/oracledb/instantclient.zip -d node_modules/oracledb/ + rm node_modules/oracledb/instantclient.zip + + DEBIAN_FRONTEND=noninteractive sudo apt-get -qq -y install libaio1 + cp /lib/*/libaio.so.* node_modules/oracledb/instantclient_19_8/ + fi + environment: + BLOB_URL: https://download.oracle.com/otn_software/linux/instantclient/19800/instantclient-basiclite-linux.x64-19.8.0.0.0dbru.zip - save_cache: + name: Save node_modules cache + key: node_modules-{{ checksum "package-lock.json" }} paths: - node_modules - key: v1-dependencies-{{ checksum "package.json" }} + +jobs: + lint: + working_directory: ~/typeorm + docker: + - image: circleci/node:12 + steps: + - checkout + - install-packages: + cache-key: node12 - run: npm run lint - - run: npm test - cockroachdb: + build: working_directory: ~/typeorm docker: - - image: circleci/node:10.15.0 - - image: cockroachdb/cockroach:latest - command: start --insecure + - image: circleci/node:12 steps: - checkout - - run: cp ormconfig.circleci-cockroach.json ormconfig.json - # Download and cache dependencies - - restore_cache: - keys: - - v1-dependencies-{{ checksum "package.json" }} - # fallback to using the latest cache if no exact match is found - - v1-dependencies- - - run: npm install - - save_cache: + - install-packages: + cache-key: node12 + - run: npm run compile + - persist_to_workspace: + root: ~/typeorm paths: - - node_modules - key: v1-dependencies-{{ checksum "package.json" }} - - run: npm run lint - - run: - npm test - oracle: + - build/ + + test: + parameters: + databases: + type: string + default: "" + node-version: + type: string + default: "10" working_directory: ~/typeorm docker: - - image: circleci/node:10.16.0 - - image: "store/oracle/database-enterprise:12.2.0.1-slim" - auth: - username: $DOCKER_USER - password: $DOCKER_PASSWORD - environment: - DB_SID: "sys" - SYS_PASSWORD: "ORCLCDB" + - image: circleci/node:<< parameters.node-version >> steps: - - run: if [ -z "$DOCKER_USER" ]; then echo "DOCKER_USER is unset"; circleci step halt; fi - checkout - - run: sudo npm install -g npm@latest - - run: cp ormconfig.circleci-oracle.json ormconfig.json + - setup_remote_docker + - attach_workspace: + at: ~/typeorm + - create-typeorm-config: + databases: << parameters.databases >> + - run: + name: Start all Relevant Services + command: | + SERVICES=$( + npx js-yaml ./docker-compose.yml \ + | jq -r '.services | keys | map(select(. | IN($ARGS.positional[]))) | join(" ")' --args << parameters.databases >> + ) + + docker-compose --project-name typeorm --no-ansi up --detach $SERVICES + - install-packages: + cache-key: node<< parameters.node-version >> + - run: + name: Set up TypeORM Test Runner + command: | + docker run \ + --volume /typeorm \ + --name typeorm-code \ + --workdir /typeorm \ + circleci/node:<< parameters.node-version >> \ + /bin/bash -c "sudo chmod 777 /typeorm && sudo chown circleci /typeorm" + docker cp ./ typeorm-code:/typeorm + - run: + name: Wait for Services to be Available + command: | + COMMANDS=$( + cat ormconfig.json \ + | jq -r ' + map(select(.skip == false) + | select(.host) + | select(.port) + | "nc -z " + .host + " " + (.port|tostring) + " && echo " + .host + " " + (.port|tostring) + " is up") + | join(" && ") + ' + ) + echo "Running '$COMMANDS'" + + docker run \ + --network typeorm_default \ + --tty \ + ubuntu:trusty \ + timeout 60 sh -c "until ($COMMANDS); do echo \"Waiting for Services to be Available ...\"; sleep 5; done" # Download and cache dependencies - - restore_cache: - keys: - - v1-dependencies-{{ checksum "package.json" }} - # fallback to using the latest cache if no exact match is found - - v1-dependencies- - - run: npm install - - save_cache: - paths: - - node_modules - key: v1-dependencies-{{ checksum "package.json" }} - - run: wget https://download.oracle.com/otn_software/linux/instantclient/195000/instantclient-basiclite-linux.x64-19.5.0.0.0dbru.zip - - run: unzip instantclient-basiclite-linux.x64-19.5.0.0.0dbru.zip -d /tmp/oracle - - run: wget https://download.oracle.com/otn_software/linux/instantclient/195000/instantclient-sqlplus-linux.x64-19.5.0.0.0dbru.zip - - run: unzip instantclient-sqlplus-linux.x64-19.5.0.0.0dbru.zip -d /tmp/oracle - - run: echo "export LD_LIBRARY_PATH=/tmp/oracle/instantclient_19_5" >> $BASH_ENV - - run: sudo sh -c "echo /tmp/oracle/instantclient_19_5 > /etc/ld.so.conf.d/oracle-instantclient.conf";sudo ldconfig - - run: sh -c 'echo WHENEVER SQLERROR EXIT FAILURE > /tmp/user.sql; echo CREATE USER typeorm IDENTIFIED BY Passw0rd\; >> /tmp/user.sql; echo GRANT CONNECT TO typeorm\; >> /tmp/user.sql; echo GRANT UNLIMITED TABLESPACE TO typeorm\; >> /tmp/user.sql; echo exit >> /tmp/user.sql' - - run: sudo apt install libaio1 - - run: until /tmp/oracle/instantclient_19_5/sqlplus -L -S sys/Oradoc_db1@//localhost:1521/orclpdb1.localdomain as sysdba @/tmp/user.sql ; do echo waiting for oracle; sleep 10; done; - - run: npm install oracledb --no-save - - run: npm run lint - - run: npm test + - run: + name: "Run Tests with Coverage" + command: | + docker run \ + --env LD_LIBRARY_PATH='/typeorm/node_modules/oracledb/instantclient_19_8/:$LD_LIBRARY_PATH' \ + --volumes-from typeorm-code \ + --network typeorm_default \ + --tty \ + --workdir /typeorm \ + --name typeorm-testrunner \ + circleci/node:<< parameters.node-version >> \ + npx nyc npm run test-fast + + docker cp typeorm-testrunner:/typeorm/coverage/ ./ + - run: + name: Stop all Relevant Services + command: docker-compose down + - store_artifacts: + path: coverage + - codecov/upload + workflows: version: 2 test: jobs: - - common - - cockroachdb - # - oracle + - lint + - build + - test: + name: test (mysql mariadb postgres mssql mongodb sqlite better-sqlite3 sqljs) - Node v<< matrix.node-version >> + requires: + - lint + - build + databases: "mysql mariadb postgres mssql mongodb sqlite better-sqlite3 sqljs" + matrix: + parameters: + node-version: + - "10" + - "12" + - "13" + - test: + name: test (cockroachdb) - Node v12 + requires: + - lint + - build + databases: "cockroachdb" + node-version: "12" + - test: + name: test (oracle) - Node v12 + requires: + - lint + - build + databases: "oracle" + node-version: "12" diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000..06473d20bf --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,54 @@ +module.exports = { + "env": { + "node": true + }, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "tsconfig.json", + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint" + ], + "rules": { + "@typescript-eslint/no-unused-vars": [ + "error", + { + "args": "none" + } + ], + "@typescript-eslint/prefer-namespace-keyword": "error", + "@typescript-eslint/quotes": [ + "error", + "double", + { + "avoidEscape": true, + "allowTemplateLiterals": true + } + ], + "@typescript-eslint/semi": [ + "error" + ], + "@typescript-eslint/type-annotation-spacing": "error", + "@typescript-eslint/no-redeclare": "error", + "eqeqeq": [ + "error", + "smart" + ], + "id-blacklist": [ + "error", + "any", + "Number", + "number", + "String", + "string", + "Boolean", + "boolean", + "Undefined", + "undefined" + ], + "id-match": "error", + "no-eval": "error", + "no-var": "error" + } +}; diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3fa8b1987b..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: node_js -node_js: - - 13 - - 12 - - 10 - -services: - - docker - -before_script: - - sudo service mysql stop - - sudo service postgresql stop - - docker-compose up -d - - cp ormconfig.travis.json ormconfig.json - -script: - - npm run lint - - npx nyc npm test - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68ff8aee7d..676a6c4ec1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,89 @@ +## [0.2.26](https://github.com/typeorm/typeorm/compare/0.2.25...0.2.26) (2020-09-10) -## 0.3.0 (next) +### Bug Fixes + +* @JoinTable does not respect inverseJoinColumns referenced column width ([#6444](https://github.com/typeorm/typeorm/issues/6444)) ([f642a9e](https://github.com/typeorm/typeorm/commit/f642a9e)), closes [#6442](https://github.com/typeorm/typeorm/issues/6442) +* add missing schema for OracleDriver ([#6673](https://github.com/typeorm/typeorm/issues/6673)) ([8b8bc35](https://github.com/typeorm/typeorm/commit/8b8bc35)) +* change InsertQueryBuilder.values() with an empty array into a no-op ([#6584](https://github.com/typeorm/typeorm/issues/6584)) ([9d2df28](https://github.com/typeorm/typeorm/commit/9d2df28)), closes [#3111](https://github.com/typeorm/typeorm/issues/3111) +* Child entities not being saved correctly with cascade actions ([#6219](https://github.com/typeorm/typeorm/issues/6219)) ([16a2d80](https://github.com/typeorm/typeorm/commit/16a2d80)) +* correctly parse connection URI with query params ([#6390](https://github.com/typeorm/typeorm/issues/6390)) ([54a3a15](https://github.com/typeorm/typeorm/commit/54a3a15)), closes [#6389](https://github.com/typeorm/typeorm/issues/6389) +* decorators should implement the official TypeScript interface ([#6398](https://github.com/typeorm/typeorm/issues/6398)) ([c23c888](https://github.com/typeorm/typeorm/commit/c23c888)), closes [#5922](https://github.com/typeorm/typeorm/issues/5922) +* DeepPartial with any and {[k: string]: any} ([#6581](https://github.com/typeorm/typeorm/issues/6581)) ([8d90d40](https://github.com/typeorm/typeorm/commit/8d90d40)), closes [#6580](https://github.com/typeorm/typeorm/issues/6580) [#6580](https://github.com/typeorm/typeorm/issues/6580) +* exporting missing load event ([#6396](https://github.com/typeorm/typeorm/issues/6396)) ([c6336aa](https://github.com/typeorm/typeorm/commit/c6336aa)) +* get correct insert ids for multiple entities inserted ([#6668](https://github.com/typeorm/typeorm/issues/6668)) ([ef2011d](https://github.com/typeorm/typeorm/commit/ef2011d)), closes [#2131](https://github.com/typeorm/typeorm/issues/2131) [#5973](https://github.com/typeorm/typeorm/issues/5973) [#2131](https://github.com/typeorm/typeorm/issues/2131) +* getPendingMigrations isn't properly working ([#6372](https://github.com/typeorm/typeorm/issues/6372)) ([7c0da1c](https://github.com/typeorm/typeorm/commit/7c0da1c)) +* handle 'error' events from pool connection ([#6262](https://github.com/typeorm/typeorm/issues/6262)) ([ae3cf0e](https://github.com/typeorm/typeorm/commit/ae3cf0e)) +* insert IN(null) instead of IN() when In([]) empty array for mysqlDriver ([#6237](https://github.com/typeorm/typeorm/issues/6237)) ([6f6bdbd](https://github.com/typeorm/typeorm/commit/6f6bdbd)) +* make only a single SELECT to get inserted default and generated values of multiple entities ([#6669](https://github.com/typeorm/typeorm/issues/6669)) ([4fc4a1b](https://github.com/typeorm/typeorm/commit/4fc4a1b)), closes [#6266](https://github.com/typeorm/typeorm/issues/6266) [#6266](https://github.com/typeorm/typeorm/issues/6266) +* Migration issues with scale & precision in sqlite/sql.js ([#6638](https://github.com/typeorm/typeorm/issues/6638)) ([0397e44](https://github.com/typeorm/typeorm/commit/0397e44)), closes [#6636](https://github.com/typeorm/typeorm/issues/6636) +* mysql migration: make sure the indices sql which left-join be the same database ([#6426](https://github.com/typeorm/typeorm/issues/6426)) ([906d97f](https://github.com/typeorm/typeorm/commit/906d97f)) +* pass `ids_` to alias builder to prevent length overflow ([#6624](https://github.com/typeorm/typeorm/issues/6624)) ([cf3ad62](https://github.com/typeorm/typeorm/commit/cf3ad62)) +* pass formatOptions to Data API Client, fix extensions ([#6404](https://github.com/typeorm/typeorm/issues/6404)) ([9abab82](https://github.com/typeorm/typeorm/commit/9abab82)), closes [#1](https://github.com/typeorm/typeorm/issues/1) +* Query builder makes query with joins, without limit for inherited entities ([#6402](https://github.com/typeorm/typeorm/issues/6402)) ([874e573](https://github.com/typeorm/typeorm/commit/874e573)), closes [#6399](https://github.com/typeorm/typeorm/issues/6399) +* remove unnecessary optionality from Raw operator's columnAlias argument ([#6321](https://github.com/typeorm/typeorm/issues/6321)) ([0d99b46](https://github.com/typeorm/typeorm/commit/0d99b46)) +* resolve missing decorators on shim ([#6354](https://github.com/typeorm/typeorm/issues/6354)) ([8e2d97d](https://github.com/typeorm/typeorm/commit/8e2d97d)), closes [#6093](https://github.com/typeorm/typeorm/issues/6093) +* revert fix handle URL objects as column field values ([#6145](https://github.com/typeorm/typeorm/issues/6145)) ([e073e02](https://github.com/typeorm/typeorm/commit/e073e02)) +* SqlQueryRunner.hasColumn was not working ([#6146](https://github.com/typeorm/typeorm/issues/6146)) ([a595fed](https://github.com/typeorm/typeorm/commit/a595fed)), closes [#5718](https://github.com/typeorm/typeorm/issues/5718) +* support multiple `JoinColumn`s in EntitySchema ([#6397](https://github.com/typeorm/typeorm/issues/6397)) ([298a3b9](https://github.com/typeorm/typeorm/commit/298a3b9)), closes [#5444](https://github.com/typeorm/typeorm/issues/5444) +* Unnecessary migrations for fulltext indices ([#6634](https://github.com/typeorm/typeorm/issues/6634)) ([c81b405](https://github.com/typeorm/typeorm/commit/c81b405)), closes [#6633](https://github.com/typeorm/typeorm/issues/6633) +* unnecessary migrations for unsigned numeric types ([#6632](https://github.com/typeorm/typeorm/issues/6632)) ([7ddaf23](https://github.com/typeorm/typeorm/commit/7ddaf23)), closes [#2943](https://github.com/typeorm/typeorm/issues/2943) [/github.com/typeorm/typeorm/pull/6632#pullrequestreview-480932808](https://github.com//github.com/typeorm/typeorm/pull/6632/issues/pullrequestreview-480932808) +* update query deep partial TypeScript definition ([#6085](https://github.com/typeorm/typeorm/issues/6085)) ([23110d1](https://github.com/typeorm/typeorm/commit/23110d1)) + +### Features + +* add AWS configurationOptions to aurora-data-api-pg connector ([#6106](https://github.com/typeorm/typeorm/issues/6106)) ([203f51d](https://github.com/typeorm/typeorm/commit/203f51d)) +* add better-sqlite3 driver ([#6224](https://github.com/typeorm/typeorm/issues/6224)) ([2241451](https://github.com/typeorm/typeorm/commit/2241451)) +* add postgres connection timeout option ([#6160](https://github.com/typeorm/typeorm/issues/6160)) ([0072149](https://github.com/typeorm/typeorm/commit/0072149)) +* FileLogger accepts custom file path ([#6642](https://github.com/typeorm/typeorm/issues/6642)) ([c99ba40](https://github.com/typeorm/typeorm/commit/c99ba40)), closes [#4410](https://github.com/typeorm/typeorm/issues/4410) +* implement postgres ltree ([#6480](https://github.com/typeorm/typeorm/issues/6480)) ([43a7386](https://github.com/typeorm/typeorm/commit/43a7386)), closes [#4193](https://github.com/typeorm/typeorm/issues/4193) +* support absolute paths in migrationsDir for the CLI ([#6660](https://github.com/typeorm/typeorm/issues/6660)) ([2b5f139](https://github.com/typeorm/typeorm/commit/2b5f139)) +* support cjs extension for ormconfig ([#6285](https://github.com/typeorm/typeorm/issues/6285)) ([6eeb03a](https://github.com/typeorm/typeorm/commit/6eeb03a)) -* find options interface was completely re-written (find options is parameter passed to find* methods) -* now query builder adds joins to eager relations by default (previously only find methods did that) -* `primary` flag has been removed from relation decorators. Now if you want to make a relation primary you must define a primary column with the same name relation uses -* added observer methods to repositories and entity manager -* `findOne` now throws error if no (or wrong) criteria supplied +## [0.2.25](https://github.com/typeorm/typeorm/compare/0.2.24...0.2.25) (2020-05-19) + +### Bug Fixes + +* 'in' clause case for ORACLE ([#5345](https://github.com/typeorm/typeorm/issues/5345)) ([8977365](https://github.com/typeorm/typeorm/commit/8977365)) +* calling EntityManager.insert() with an empty array of entities ([#5745](https://github.com/typeorm/typeorm/issues/5745)) ([f8c52f3](https://github.com/typeorm/typeorm/commit/f8c52f3)), closes [#5734](https://github.com/typeorm/typeorm/issues/5734) [#5734](https://github.com/typeorm/typeorm/issues/5734) [#5734](https://github.com/typeorm/typeorm/issues/5734) +* columns with transformer should be normalized for update ([#5700](https://github.com/typeorm/typeorm/issues/5700)) ([4ef6b65](https://github.com/typeorm/typeorm/commit/4ef6b65)), closes [#2703](https://github.com/typeorm/typeorm/issues/2703) +* escape column comment in mysql driver ([#6056](https://github.com/typeorm/typeorm/issues/6056)) ([5fc802d](https://github.com/typeorm/typeorm/commit/5fc802d)) +* expo sqlite driver disconnect() ([#6027](https://github.com/typeorm/typeorm/issues/6027)) ([61d59ca](https://github.com/typeorm/typeorm/commit/61d59ca)) +* HANA - SSL options, column delta detection mechanism ([#5938](https://github.com/typeorm/typeorm/issues/5938)) ([2fd0a8a](https://github.com/typeorm/typeorm/commit/2fd0a8a)) +* handle URL objects as column field values ([#5771](https://github.com/typeorm/typeorm/issues/5771)) ([50a0641](https://github.com/typeorm/typeorm/commit/50a0641)), closes [#5762](https://github.com/typeorm/typeorm/issues/5762) [#5762](https://github.com/typeorm/typeorm/issues/5762) +* insert and update query builder to handle mssql geometry column correctly ([#5947](https://github.com/typeorm/typeorm/issues/5947)) ([87cc6f4](https://github.com/typeorm/typeorm/commit/87cc6f4)) +* migrations being generated for FK even if there are no changes ([#5869](https://github.com/typeorm/typeorm/issues/5869)) ([416e419](https://github.com/typeorm/typeorm/commit/416e419)) +* multiple assignments to same column on UPDATE [#2651](https://github.com/typeorm/typeorm/issues/2651) ([#5598](https://github.com/typeorm/typeorm/issues/5598)) ([334e17e](https://github.com/typeorm/typeorm/commit/334e17e)) +* prevent TypeError when calling bind function with sql.js 1.2.X ([#5789](https://github.com/typeorm/typeorm/issues/5789)) ([c6cbddc](https://github.com/typeorm/typeorm/commit/c6cbddc)) +* prototype pollution issue ([#6096](https://github.com/typeorm/typeorm/issues/6096)) ([db9d0fa](https://github.com/typeorm/typeorm/commit/db9d0fa)) +* provide a default empty array for parameters. ([#5677](https://github.com/typeorm/typeorm/issues/5677)) ([9e8a8cf](https://github.com/typeorm/typeorm/commit/9e8a8cf)) +* redundant undefined parameters are not generated in migration files anymore ([#5690](https://github.com/typeorm/typeorm/issues/5690)) ([d5cde49](https://github.com/typeorm/typeorm/commit/d5cde49)) +* replacing instanceof Array checks to Array.isArray because instanceof Array seems to be problematic on some platforms ([#5606](https://github.com/typeorm/typeorm/issues/5606)) ([b99b4ad](https://github.com/typeorm/typeorm/commit/b99b4ad)) +* respect database from connection urls ([#5640](https://github.com/typeorm/typeorm/issues/5640)) ([ed75d59](https://github.com/typeorm/typeorm/commit/ed75d59)), closes [#2096](https://github.com/typeorm/typeorm/issues/2096) +* sha.js import ([#5728](https://github.com/typeorm/typeorm/issues/5728)) ([8c3f48a](https://github.com/typeorm/typeorm/commit/8c3f48a)) +* Unknown fields are stripped from WHERE clause (issue [#3416](https://github.com/typeorm/typeorm/issues/3416)) ([#5603](https://github.com/typeorm/typeorm/issues/5603)) ([215f106](https://github.com/typeorm/typeorm/commit/215f106)) +* update dependency mkdirp to 1.x ([#5748](https://github.com/typeorm/typeorm/issues/5748)) ([edeb561](https://github.com/typeorm/typeorm/commit/edeb561)) +* update Entity decorator return type to ClassDecorator ([#5776](https://github.com/typeorm/typeorm/issues/5776)) ([7d8a1ca](https://github.com/typeorm/typeorm/commit/7d8a1ca)) +* use an empty string enum as the type of a primary key column ([#6063](https://github.com/typeorm/typeorm/issues/6063)) ([8e0d817](https://github.com/typeorm/typeorm/commit/8e0d817)), closes [#3874](https://github.com/typeorm/typeorm/issues/3874) +* use correct typings for the result of `getUpsertedIds()` ([#5878](https://github.com/typeorm/typeorm/issues/5878)) ([2ab88c2](https://github.com/typeorm/typeorm/commit/2ab88c2)) +* wrong table name parameter when not using default schema ([#5801](https://github.com/typeorm/typeorm/issues/5801)) ([327144a](https://github.com/typeorm/typeorm/commit/327144a)) + +### Features + +* add FOR NO KEY UPDATE lock mode for postgresql ([#5971](https://github.com/typeorm/typeorm/issues/5971)) ([360122f](https://github.com/typeorm/typeorm/commit/360122f)) +* add name option to view column ([#5962](https://github.com/typeorm/typeorm/issues/5962)) ([3cfcc50](https://github.com/typeorm/typeorm/commit/3cfcc50)), closes [#5708](https://github.com/typeorm/typeorm/issues/5708) +* Add soft remove and recover methods to entity ([#5854](https://github.com/typeorm/typeorm/issues/5854)) ([9d2b8e0](https://github.com/typeorm/typeorm/commit/9d2b8e0)) +* added support for NOWAIT & SKIP LOCKED in Postgres ([#5927](https://github.com/typeorm/typeorm/issues/5927)) ([2c90e1c](https://github.com/typeorm/typeorm/commit/2c90e1c)) +* Aurora Data API - Postgres Support ([#5651](https://github.com/typeorm/typeorm/issues/5651)) ([e584297](https://github.com/typeorm/typeorm/commit/e584297)) +* aurora Data API - Support for AWS configuration options through aurora driver ([#5754](https://github.com/typeorm/typeorm/issues/5754)) ([1829f96](https://github.com/typeorm/typeorm/commit/1829f96)) +* create-column, update-column, version-column column kinds now support user specified values ([#5867](https://github.com/typeorm/typeorm/issues/5867)) ([5a2eb30](https://github.com/typeorm/typeorm/commit/5a2eb30)), closes [#3271](https://github.com/typeorm/typeorm/issues/3271) +* names of extra columns for specific tree types moved to NamingStrategy ([#5737](https://github.com/typeorm/typeorm/issues/5737)) ([ec3be41](https://github.com/typeorm/typeorm/commit/ec3be41)) +* PG allow providing a function for password ([#5673](https://github.com/typeorm/typeorm/issues/5673)) ([265d1ae](https://github.com/typeorm/typeorm/commit/265d1ae)) +* update cli migration up and down from any to void ([#5630](https://github.com/typeorm/typeorm/issues/5630)) ([76e165d](https://github.com/typeorm/typeorm/commit/76e165d)) +* UpdateResult returns affected rows in mysql ([#5628](https://github.com/typeorm/typeorm/issues/5628)) ([17f2fff](https://github.com/typeorm/typeorm/commit/17f2fff)), closes [#1308](https://github.com/typeorm/typeorm/issues/1308) + +### Performance Improvements + +* An optimized version of EntityMetadata#compareIds() for the common case ([#5419](https://github.com/typeorm/typeorm/issues/5419)) ([a9bdb37](https://github.com/typeorm/typeorm/commit/a9bdb37)) ## [0.2.23](https://github.com/typeorm/typeorm/compare/0.2.22...0.2.23), [0.2.24](https://github.com/typeorm/typeorm/compare/0.2.23...0.2.24) (2020-02-28) @@ -34,7 +112,6 @@ ## [0.2.22](https://github.com/typeorm/typeorm/compare/0.2.21...0.2.22) (2019-12-23) - ### Bug Fixes * use a prefix on SelectQueryBuilder internal parameters ([#5178](https://github.com/typeorm/typeorm/issues/5178)) ([cacb08b](https://github.com/typeorm/typeorm/commit/cacb08b)), closes [#5174](https://github.com/typeorm/typeorm/issues/5174) [#5174](https://github.com/typeorm/typeorm/issues/5174) @@ -190,7 +267,11 @@ * fixed: changes in enum type is not reflected when generating migration (in definition file) ([#3244](https://github.com/typeorm/typeorm/issues/3244)) * fixed: migration will keep create and drop indexes if index name is the same across tables ([#3379](https://github.com/typeorm/typeorm/issues/3379)) -## 0.2.15 +### Features + +* added `lock` option in `FindOptions` + +## 0.2.15 (2019-03-14) ### Bug fixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3c619c186f..e92a577913 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ As a contributor, here are the guidelines we would like you to follow: There are several ways how you can ask your question: * You can create a question on [StackOverflow](https://stackoverflow.com/questions/tagged/typeorm) where the questions should be tagged with tag `typeorm`. -* You can ask on [Slack](https://join.slack.com/t/typeorm/shared_invite/enQtNDQ1MzA3MDA5MTExLTUxNTZhM2Q4NDNhMjMzNjQ2NGM1ZjI1ZGRkNjJjYzI4OTZjMGYyYTc0MzAxYTdjMWE3ZDIxOWUzZTdlM2QxNTY) +* You can ask on [Slack](https://join.slack.com/t/typeorm/shared_invite/zt-gej3gc00-hR~L~DqGUJ7qOpGy4SSq3g) * You can create issue on [github](https://github.com/typeorm/typeorm/issues) * If you have a Skype then try to find me there (`Umed Khudoiberdiev`) diff --git a/DEVELOPER.md b/DEVELOPER.md index 90bb338568..b365fbcda1 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -69,23 +69,6 @@ To create an initial `ormconfig.json` file, run the following command: cp ormconfig.json.dist ormconfig.json ``` -## Compiling - -To transpile for running tests, run - -```shell -npm run compile -``` - ->**Hint:** because transpiling the full project can take a while, you can set typescript to ->compile in 'watch' mode, where it will only compile modified files when they are saved. -> ->```shell ->npm run compile -- -w ->``` -> ->This is useful when you are making changes to either production code or tests and iterating. - ## Building To build a distribution package of TypeORM run: @@ -148,15 +131,6 @@ Then run tests: npm test ``` ->**Hint:** running ```npm test``` will transpile before running tests. If you have already compiled, or are ->letting typescript run in watch mode, you can execute: -> ->```shell ->npm run test-no-compile ->``` -> ->which omits the compile step. - You should execute test suites before submitting a PR to github. All the tests are executed on our Continuous Integration infrastructure and a PR could only be merged once the tests pass. @@ -179,7 +153,7 @@ describe.only('your describe test', ....) The `npm test` script works by deleting built TypeScript code, rebuilding the codebase, and then running tests. This can take a long time. -Instead, for a quicker feedback cycle, you can run `npm run compile --watch` to make a fresh build and instruct TypeScript to watch for changes and only compile what code you've changed. +Instead, for a quicker feedback cycle, you can run `npm run compile -- --watch` to make a fresh build and instruct TypeScript to watch for changes and only compile what code you've changed. Once TypeScript finishes compiling your changes, you can run `npm run test-fast` (instead of `test`), to trigger a test without causing a full recompile, which allows you to edit and check your changes much faster. diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 8e96c64ffa..7dc654f615 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,6 +1,12 @@ **Issue type:** -[ ] question + + [ ] bug report [ ] feature request [ ] documentation issue diff --git a/README-zh_CN.md b/README-zh_CN.md index 2c6f2e2806..4b7dc796d9 100644 --- a/README-zh_CN.md +++ b/README-zh_CN.md @@ -4,8 +4,8 @@

- - + + @@ -22,13 +22,13 @@ TypeORM 是一个 [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping) 框架,它可以运行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo 和 Electron 平台上,可以与 TypeScript 和 JavaScript (ES5,ES6,ES7,ES8)一起使用。 它的目标是始终支持最新的 JavaScript 特性并提供额外的特性以帮助你开发任何使用数据库的(不管是只有几张表的小型应用还是拥有多数据库的大型企业应用)应用程序。 -不同于现有的所有其他 JavaScript ORM 框架,TypeORM 支持 [Active Record](./docs/active-record-data-mapper.md#what-is-the-active-record-pattern) 和 [Data Mapper](./docs/active-record-data-mapper.md#what-is-the-data-mapper-pattern) 模式,这意味着你可以以最高效的方式编写高质量的、松耦合的、可扩展的、可维护的应用程序。 +不同于现有的所有其他 JavaScript ORM 框架,TypeORM 支持 [Data Mapper](./docs/zh_CN/active-record-data-mapper.md#什么是data-mapper模式) 和 [Active Record](./docs/zh_CN/active-record-data-mapper.md#什么是active-record模式) 模式,这意味着你可以以最高效的方式编写高质量的、松耦合的、可扩展的、可维护的应用程序。 TypeORM 参考了很多其他优秀 ORM 的实现, 比如 [Hibernate](http://hibernate.org/orm/), [Doctrine](http://www.doctrine-project.org/) 和 [Entity Framework](https://www.asp.net/entity-framework)。 TypeORM 的一些特性: -- 同时支持 [DataMapper](./docs/active-record-data-mapper.md#what-is-the-data-mapper-pattern) 和 [ActiveRecord](./docs/active-record-data-mapper.md#what-is-the-active-record-pattern) (随你选择) +- 同时支持 [DataMapper](./docs/zh_CN/active-record-data-mapper.md#什么是data-mapper模式) 和 [ActiveRecord](./docs/zh_CN/active-record-data-mapper.md#什么是active-record模式) (随你选择) - 实体和列 - 数据库特性列类型 - 实体管理 @@ -69,7 +69,7 @@ TypeORM 的一些特性: 通过使用 `TypeORM` 你的 `models` 看起来如下: -```typescript +```ts import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"; @Entity() @@ -90,7 +90,7 @@ export class User { 逻辑操作如下: -```typescript +```ts const user = new User(); user.firstName = "Timber"; user.lastName = "Saw"; @@ -106,7 +106,7 @@ await repository.remove(timber); 或者,如果你更喜欢使用 `ActiveRecord` 模式,也可以这样用: -```typescript +```ts import { Entity, PrimaryGeneratedColumn, Column, BaseEntity } from "typeorm"; @Entity() @@ -127,7 +127,7 @@ export class User extends BaseEntity { 逻辑操作如下所示: -```typescript +```ts const user = new User(); user.firstName = "Timber"; user.lastName = "Saw"; @@ -241,7 +241,7 @@ typeorm init --name MyProject --database mysql 此命令将在 `MyProject` 目录中生成一个包含以下文件的新项目: -``` +```sh MyProject ├── src // TypeScript 代码 │ ├── entity // 存储实体(数据库模型)的位置 @@ -259,9 +259,9 @@ MyProject 接下来安装项目依赖项: -``` -cd MyProject -npm install +```sh +$ cd MyProject +$ npm install ``` 在安装过程中,编辑 `ormconfig.json` 文件并在其中编辑自己的数据库连接配置选项: @@ -286,8 +286,8 @@ npm install 完成配置并安装所有 node modules 后,即可运行应用程序: -``` -npm start +```sh +$ npm start ``` 至此你的应用程序应该成功运行并将新用户插入数据库。你可以继续使用此项目并集成所需的其他模块并创建更多实体。 @@ -305,7 +305,7 @@ npm start 举个例子, 你有一个 `Photo` 模型: -```typescript +```ts export class Photo { id: number; name: string; @@ -323,7 +323,7 @@ export class Photo { 让我们将 `Photo` 模型作为一个实体 -```typescript +```ts import { Entity } from "typeorm"; @Entity() @@ -344,7 +344,7 @@ export class Photo { 要添加数据库列,你只需要将要生成的实体属性加上 `@Column` 装饰器。 -```typescript +```ts import { Entity, Column } from "typeorm"; @Entity() @@ -378,7 +378,7 @@ export class Photo { 每个**必须**至少有一个主键列。这是必须的,你无法避免。要使列成为主键,你需要使用 `@PrimaryColumn` 装饰器。 -```typescript +```ts import { Entity, Column, PrimaryColumn } from "typeorm"; @Entity() @@ -407,7 +407,7 @@ export class Photo { 假设你希望 id 列自动生成(这称为 auto-increment/sequence/serial/generated identity column)。为此你需要将`@PrimaryColumn` 装饰器更改为 `@PrimaryGeneratedColumn` 装饰器: -```typescript +```ts import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"; @Entity() @@ -437,7 +437,7 @@ export class Photo { 接下来,让我们修改数据类型。默认情况下,字符串被映射到一个 varchar(255) 类型(取决于数据库类型)。 数字被映射到一个类似 integer 类型(取决于数据库类型)。但是我们不希望所有的列都是有限的 varchars 或 integer,让我们修改下代码以设置想要的数据类型: -```typescript +```ts import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"; @Entity() @@ -464,13 +464,13 @@ export class Photo { } ``` -列类型是特定于数据库的。你可以设置数据库支持的任何列类型。有关支持的列类型的更多信息,请参见[此处](./docs/entities.md#column-types)。 +列类型是特定于数据库的。你可以设置数据库支持的任何列类型。有关支持的列类型的更多信息,请参见[此处](./docs/zh_CN/entities.md#列类型)。 ### 创建数据库的连接 当实体被创建后,让我们创建一个`index.ts`(或`app.ts`,无论你怎么命名)文件,并配置数据库连接:: -```typescript +```ts import "reflect-metadata"; import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; @@ -502,7 +502,7 @@ createConnection({ 之后当我们创建更多实体时,都需要一一将它们添加到配置中的实体中,但是这不是很方便,所以我们可以设置加载整个目录,从中连接所有实体并使用: -```typescript +```ts import { createConnection } from "typeorm"; createConnection({ @@ -547,7 +547,7 @@ createConnection({ 现在创建一个新的 photo 存到数据库: -```typescript +```ts import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; @@ -573,7 +573,7 @@ createConnection(/*...*/) 我们可以使用ES8(ES2017)的新特性,并使用 async/await 语法代替: -```typescript +```ts import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; @@ -598,7 +598,7 @@ createConnection(/*...*/) 例如,加载已经保存的实体: -```typescript +```ts import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; @@ -613,13 +613,13 @@ createConnection(/*...*/) `savedPhotos` 是一个 Photo 对象数组,其中包含从数据库加载的数据。 -了解更多有关 [EntityManager](./docs/working-with-entity-manager.md) 的信息。 +了解更多有关 [EntityManager](./docs/zh_CN/working-with-entity-manager.md) 的信息。 ### 使用 Repositories 现在让我们重构之前的代码,并使用 `Repository` 替代 `EntityManager`。每个实体都有自己的repository,可以处理其实体的所有操作。当你经常处理实体时,Repositories 比 EntityManagers 更方便使用: -```typescript +```ts import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; @@ -643,13 +643,13 @@ createConnection(/*...*/) .catch(error => console.log(error)); ``` -了解更多有关 [Repository](./docs/working-with-repository.md) 的信息。 +了解更多有关 [Repository](./docs/zh_CN/working-with-repository.md) 的信息。 ### 从数据库加载 让我们使用 Repository 尝试更多的加载操作: -```typescript +```ts import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; @@ -682,7 +682,7 @@ createConnection(/*...*/) 让我们从数据库加载出 photo,更新并保存到数据库: -```typescript +```ts import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; @@ -702,7 +702,7 @@ createConnection(/*...*/) 让我们从数据库中删除 Photo: -```typescript +```ts import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; @@ -721,7 +721,7 @@ createConnection(/*...*/) 要与另一个类创建一对一的关系。先在 `PhotoMetadata.ts` 中创建一个新类。此 PhotoMetadata 类应包含 photo 的其他元信息: -```typescript +```ts import { Entity, Column, PrimaryGeneratedColumn, OneToOne, JoinColumn } from "typeorm"; import { Photo } from "./Photo"; @@ -777,7 +777,7 @@ export class PhotoMetadata { 现在让我们来创建一个 photo,它的元信息将它们互相连接起来。 -```typescript +```ts import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; import { PhotoMetadata } from "./entity/PhotoMetadata"; @@ -820,7 +820,7 @@ createConnection(/*...*/) 关系可以是单向的或双向的。目前 PhotoMetadata 和 Photo 之间的关系是单向的。关系的所有者是 PhotoMetadata,而 Photo 对 PhotoMetadata 一无所知。这使得从 Photo 中访问 PhotoMetadata 变得很复杂。要解决这个问题,我们应该在 PhotoMetadata 和 Photo 之间建立双向关系。让我们来修改一下实体: -```typescript +```ts import { Entity, Column, PrimaryGeneratedColumn, OneToOne, JoinColumn } from "typeorm"; import { Photo } from "./Photo"; @@ -855,7 +855,7 @@ export class Photo { 在一个查询中加载 photo 及 photo metadata 有两种方法。使用 `find *` 或使用 `QueryBuilder`。我们先使用 `find *` 方法。 `find *` 方法允许你使用 `FindOneOptions` / `FindManyOptions` 接口指定对象。 -```typescript +```ts import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; import { PhotoMetadata } from "./entity/PhotoMetadata"; @@ -869,11 +869,11 @@ createConnection(/*...*/) .catch(error => console.log(error)); ``` -photos 包含来自数据库的 photos 数组,每个 photo 包含其 photo metadata。详细了解本文档中的[Find 选项](./docs/find-options.md)。 +photos 包含来自数据库的 photos 数组,每个 photo 包含其 photo metadata。详细了解本文档中的[Find 选项](./docs/zh_CN/find-options.md)。 使用find选项很简单,但是如果你需要更复杂的查询,则应该使用 `QueryBuilder`。 `QueryBuilder` 使用更优雅的方式执行更复杂的查询: -```typescript +```ts import { createConnection } from "typeorm"; import { Photo } from "./entity/Photo"; import { PhotoMetadata } from "./entity/PhotoMetadata"; @@ -896,7 +896,7 @@ createConnection(/*...*/) 我们可以在关系中设置 `cascade` 选项,这时就可以在保存其他对象的同时保存相关对象。让我们更改一下的 photo 的 `@OneToOne` 装饰器: -```typescript +```ts export class Photo { /// ... 其他列 @@ -909,7 +909,7 @@ export class Photo { 使用 `cascade` 允许就不需要边存 photo 边存元数据对象。我们可以简单地保存一个 photo 对象,由于使用了 cascade,metadata 也将自动保存。 -```typescript +```ts createConnection(options) .then(async connection => { // 创建 photo 对象 @@ -966,7 +966,7 @@ export class Author { 现在让我们将关系的所有者方添加到 Photo 实体中: -```typescript +```ts import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from "typeorm"; import { PhotoMetadata } from "./PhotoMetadata"; import { Author } from "./Author"; @@ -1011,7 +1011,7 @@ export class Photo { 假设一个 photo 可以放在多个 albums 中,每个 albums 可以包含多个 photo。让我们创建一个`Album`类: -```typescript +```ts import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from "typeorm"; @Entity() @@ -1032,7 +1032,7 @@ export class Album { 现在添加反向关系到`Photo`类: -```typescript +```ts export class Photo { /// ... 其他列 @@ -1054,7 +1054,7 @@ export class Photo { 记得在 ORM 中使用 ConnectionOptions 注册`Album`类: -```typescript +```ts const options: ConnectionOptions = { // ... 其他选项 entities: [Photo, PhotoMetadata, Author, Album] @@ -1063,7 +1063,7 @@ const options: ConnectionOptions = { 现在让我们将 albums 和 photos 插入我们的数据库: -```typescript +```ts let connection = await createConnection(options); // 创建一些 albums @@ -1090,7 +1090,7 @@ const loadedPhoto = await connection.getRepository(Photo).findOne(1, { relations `loadedPhoto` 如下所示: -```typescript +```ts { id: 1, name: "Me and Bears", @@ -1110,7 +1110,7 @@ const loadedPhoto = await connection.getRepository(Photo).findOne(1, { relations 你可以使用 QueryBuilder 构建几乎任何复杂性的 SQL 查询。例如,可以这样做: -```typescript +```ts let photos = await connection .getRepository(Photo) .createQueryBuilder("photo") // 第一个参数是别名。即photos。 该参数必须指定。 @@ -1128,7 +1128,7 @@ let photos = await connection 此查询选择所有 published 的 name 等于"My"或"Mishka"的 photos。它将从结果中的第 5 个(分页偏移)开始,并且仅选择 10 个结果(分页限制)。得到的结果将按 ID 降序排序。photo 的 albums 将被 left-joined,其元数据将被 inner joined。 由于 QueryBuilder 的自由度更高,因此在项目中可能会大量的使用它。 -更多关于 QueryBuilder 的信息,[可查看](./docs/select-query-builder.md)。 +更多关于 QueryBuilder 的信息,[可查看](./docs/zh_CN/select-query-builder.md)。 ## 示例 diff --git a/README.md b/README.md index 516b37cdd5..72f9b72e45 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@

- - + + @@ -16,7 +16,7 @@ Codecov - +
@@ -38,8 +38,8 @@ maintainable applications the most productive way. TypeORM is highly influenced by other ORMs, such as [Hibernate](http://hibernate.org/orm/), [Doctrine](http://www.doctrine-project.org/) and [Entity Framework](https://www.asp.net/entity-framework). - -Some TypeORM features: + +## Features * supports both [DataMapper](./docs/active-record-data-mapper.md#what-is-the-data-mapper-pattern) and [ActiveRecord](./docs/active-record-data-mapper.md#what-is-the-active-record-pattern) (your choice) * entities and columns @@ -106,6 +106,8 @@ export class User { And your domain logic looks like this: ```typescript +const repository = connection.getRepository(User); + const user = new User(); user.firstName = "Timber"; user.lastName = "Saw"; @@ -175,7 +177,7 @@ await timber.remove(); 3. You may need to install node typings: - `npm install @types/node --save` + `npm install @types/node --save-dev` 4. Install a database driver: @@ -213,6 +215,8 @@ await timber.remove(); npm i @sap/hana-client npm i hdb-pool ``` + + *SAP Hana support made possible by sponsorship of [Neptune Software](https://www.neptune-software.com/).* * for **MongoDB** (experimental) @@ -880,7 +884,7 @@ createConnection(/*...*/).then(async connection => { metadata.width = 480; metadata.compressed = true; metadata.comment = "cybershoot"; - metadata.orientation = "portait"; + metadata.orientation = "portrait"; metadata.photo = photo; // this way we connect them // get entity repositories @@ -1031,7 +1035,7 @@ createConnection(options).then(async connection => { metadata.width = 480; metadata.compressed = true; metadata.comment = "cybershoot"; - metadata.orientation = "portait"; + metadata.orientation = "portrait"; photo.metadata = metadata; // this way we connect them diff --git a/docker-compose.yml b/docker-compose.yml index 2967b92789..47415bce4e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -62,12 +62,18 @@ services: # cockroachdb cockroachdb: - image: "cockroachdb/cockroach:v19.2.4" + image: "cockroachdb/cockroach:v19.2.9" container_name: "typeorm-cockroachdb" command: start --insecure ports: - "26257:26257" + oracle: + image: imnotjames/oracle-xe:18 + container_name: "typeorm-oracle" + ports: + - "1521:1521" + # sap hana (works only on linux) # hanaexpress: # image: "store/saplabs/hanaexpress:2.00.040.00.20190729.1" diff --git a/docs/connection-api.md b/docs/connection-api.md index ed65ddb5fe..0081f1955f 100644 --- a/docs/connection-api.md +++ b/docs/connection-api.md @@ -295,7 +295,7 @@ const users = await connection.createQueryBuilder() .getMany(); ``` -* `createQueryRunner` - Creates a query runner used manage and work with a single real database connection. +* `createQueryRunner` - Creates a query runner used to manage and work with a single real database connection. Learn more about [QueryRunner](./query-runner.md). ```typescript diff --git a/docs/connection-options.md b/docs/connection-options.md index 975db72023..219e141050 100644 --- a/docs/connection-options.md +++ b/docs/connection-options.md @@ -5,6 +5,7 @@ * [`mysql` / `mariadb` connection options](#mysql--mariadb-connection-options) * [`postgres` / `cockroachdb` connection options](#postgres--cockroachdb-connection-options) * [`sqlite` connection options](#sqlite-connection-options) +* [`better-sqlite3` connection options](#better-sqlite3-connection-options) * [`cordova` connection options](#cordova-connection-options) * [`react-native` connection options](#react-native-connection-options) * [`nativescript` connection options](#nativescript-connection-options) @@ -22,7 +23,7 @@ Connection options is a connection configuration you pass to `createConnection` ## Common connection options * `type` - Database type. You must specify what database engine you use. - Possible values are "mysql", "postgres", "cockroachdb", "mariadb", "sqlite", "cordova", "nativescript", + Possible values are "mysql", "postgres", "cockroachdb", "mariadb", "sqlite", "better-sqlite3", "cordova", "nativescript", "oracle", "mssql", "mongodb", "sqljs", "react-native". This option is **required**. @@ -34,11 +35,12 @@ If connection name is not given then it will be called "default". * `extra` - Extra connection options to be passed to the underlying driver. Use it if you want to pass extra settings to underlying database driver. -* `entities` - Entities to be loaded and used for this connection. -Accepts both entity classes and directories paths to load from. +* `entities` - Entities, or Entity Schemas, to be loaded and used for this connection. +Accepts both entity classes, entity schema classes, and directories paths to load from. Directories support glob patterns. Example: `entities: [Post, Category, "entity/*.js", "modules/**/entity/*.js"]`. -Learn more about [Entities](./entities.md). +Learn more about [Entities](./entities.md). +Learn more about [Entity Schemas](separating-entity-definition.md). * `subscribers` - Subscribers to be loaded and used for this connection. Accepts both entity classes and directories to load from. @@ -46,12 +48,6 @@ Directories support glob patterns. Example: `subscribers: [PostSubscriber, AppSubscriber, "subscriber/*.js", "modules/**/subscriber/*.js"]`. Learn more about [Subscribers](listeners-and-subscribers.md). -* `entitySchemas` - Entity schemas to be loaded and used for this connection. -Accepts both entity schema classes and directories to load from. -Directories support glob patterns. -Example: `entitySchemas: [PostSchema, CategorySchema, "entity-schema/*.json", "modules/**/entity-schema/*.json"]`. -Learn more about [Entity Schemas](separating-entity-definition.md). - * `migrations` - Migrations to be loaded and used for this connection. Accepts both migration classes and directories to load from. Directories support glob patterns. @@ -178,16 +174,28 @@ See [SSL options](https://github.com/mysqljs/mysql#ssl-options). * `schema` - Schema name. Default is "public". +* `connectTimeoutMS` - The milliseconds before a timeout occurs during the initial connection to the postgres server. If `undefined`, or set to `0`, there is no timeout. Defaults to `undefined`. + * `ssl` - Object with ssl parameters. See [TLS/SSL](https://node-postgres.com/features/ssl). * `uuidExtension` - The Postgres extension to use when generating UUIDs. Defaults to `uuid-ossp`. Can be changed to `pgcrypto` if the `uuid-ossp` extension is unavailable. * `poolErrorHandler` - A function that get's called when underlying pool emits `'error'` event. Takes single parameter (error instance) and defaults to logging with `warn` level. +* `logNotifications` - A boolean to determine whether postgres server [notice messages](https://www.postgresql.org/docs/current/plpgsql-errors-and-messages.html) and [notification events](https://www.postgresql.org/docs/current/sql-notify.html) should be included in client's logs with `info` level (default: `false`). + ## `sqlite` connection options * `database` - Database path. For example "./mydb.sql" +## `better-sqlite3` connection options + +* `database` - Database path. For example "./mydb.sql" + +* `statementCacheSize` - Cache size of sqlite statement to speed up queries (default 100). + +* `prepareDatabase` - Function to run before a database is used in typeorm. You can access original better-sqlite3 Database object here. + ## `cordova` connection options * `database` - Database name diff --git a/docs/decorator-reference.md b/docs/decorator-reference.md index 6a6ede3fa3..438dbd20eb 100644 --- a/docs/decorator-reference.md +++ b/docs/decorator-reference.md @@ -10,6 +10,7 @@ * [`@ObjectIdColumn`](#objectidcolumn) * [`@CreateDateColumn`](#createdatecolumn) * [`@UpdateDateColumn`](#updatedatecolumn) + * [`@DeleteDateColumn`](#deletedatecolumn) * [`@VersionColumn`](#versioncolumn) * [`@Generated`](#generated) * [Relation decorators](#relation-decorators) @@ -93,7 +94,7 @@ View entity is a class that maps to a database view. `expression` can be string with properly escaped columns and tables, depend on database used (postgres in example): ```typescript -@ViewEntity({ +@ViewEntity({ expression: ` SELECT "post"."id" "id", "post"."name" AS "name", "category"."name" AS "categoryName" FROM "post" "post" @@ -106,7 +107,7 @@ export class PostCategory { or an instance of QueryBuilder ```typescript -@ViewEntity({ +@ViewEntity({ expression: (connection: Connection) => connection.createQueryBuilder() .select("post.id", "id") .addSelect("post.name", "name") @@ -120,7 +121,7 @@ export class PostCategory { **Note:** parameter binding is not supported due to drivers limitations. Use the literal parameters instead. ```typescript -@ViewEntity({ +@ViewEntity({ expression: (connection: Connection) => connection.createQueryBuilder() .select("post.id", "id") .addSelect("post.name", "name") @@ -192,6 +193,7 @@ If `true`, MySQL automatically adds the `UNSIGNED` attribute to this column. * `collation: string` - Defines a column collation. * `enum: string[]|AnyEnum` - Used in `enum` column type to specify list of allowed enum values. You can specify array of values or specify a enum class. +* `enumName: string` - A name for generated enum type. If not specified, TypeORM will generate a enum type from entity and column names - so it's neccessary if you intend to use the same enum type in different tables. * `asExpression: string` - Generated column expression. Used only in [MySQL](https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html). * `generatedType: "VIRTUAL"|"STORED"` - Generated column type. Used only in [MySQL](https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html). * `hstoreType: "object"|"string"` - Return type of `HSTORE` column. Returns value as string or as object. Used only in [Postgres](https://www.postgresql.org/docs/9.6/static/hstore.html). @@ -240,7 +242,7 @@ There are two generation strategies: * `increment` - uses AUTO_INCREMENT / SERIAL / SEQUENCE (depend on database type) to generate incremental number. * `uuid` - generates unique `uuid` string. -* `rowid` - only for [CockroachDB](https://www.cockroachlabs.com/docs/stable/serial.html). Value is automatically generated using the `unique_rowid()` +* `rowid` - only for [CockroachDB](https://www.cockroachlabs.com/docs/stable/serial.html). Value is automatically generated using the `unique_rowid()` function. This produces a 64-bit integer from the current timestamp and ID of the node executing the `INSERT` or `UPSERT` operation. > Note: property with a `rowid` generation strategy must be a `string` data type @@ -309,6 +311,24 @@ export class User { } ``` +#### `@DeleteDateColumn` + +Special column that is automatically set to the entity's delete time each time you call soft-delete of entity manager or repository. You don't need to set this column - it will be automatically set. + +TypeORM's own soft delete functionality utilizes global scopes to only pull "non-deleted" entities from the database. + +If the @DeleteDateColumn is set, the default scope will be "non-deleted". + +```typescript +@Entity() +export class User { + + @DeleteDateColumn() + deletedDate: Date; + +} +``` + #### `@VersionColumn` Special column that is automatically set to the entity's version (incremental number) diff --git a/docs/delete-query-builder.md b/docs/delete-query-builder.md index 0611e7f0c7..8c679ca483 100644 --- a/docs/delete-query-builder.md +++ b/docs/delete-query-builder.md @@ -1,8 +1,15 @@ # Delete using Query Builder +* [Delete using Query Builder](#delete-using-query-builder) + * [`Delete`](#delete) + * [`Soft-Delete`](#soft-delete) + * [`Restore-Soft-Delete`](#restore-soft-delete) + +### `Delete` + You can create `DELETE` queries using `QueryBuilder`. Examples: - + ```typescript import {getConnection} from "typeorm"; @@ -14,4 +21,42 @@ await getConnection() .execute(); ``` -This is the most efficient way in terms of performance to delete entities from your database. +This is the most efficient way in terms of performance to delete entities from your database. + +--- + +### `Soft-Delete` + +Applying Soft Delete to QueryBuilder + +```typescript +import {createConnection} from "typeorm"; +import {Entity} from "./entity"; + +createConnection(/*...*/).then(async connection => { + + await connection + .getRepository(Entity) + .createQueryBuilder() + .softDelete() + +}).catch(error => console.log(error)); +``` + +### `Restore-Soft-Delete` + +Alternatively, You can recover the soft deleted rows by using the `restore()` method: + +```typescript +import {createConnection} from "typeorm"; +import {Entity} from "./entity"; + +createConnection(/*...*/).then(async connection => { + + await connection + .getRepository(Entity) + .createQueryBuilder() + .restore() + +}).catch(error => console.log(error)); +``` diff --git a/docs/entities.md b/docs/entities.md index 1fed3d7826..9b562454ce 100644 --- a/docs/entities.md +++ b/docs/entities.md @@ -200,6 +200,8 @@ You don't need to set this column - it will be automatically set. each time you call `save` of entity manager or repository. You don't need to set this column - it will be automatically set. +* `@DeleteDateColumn` is a special column that is automatically set to the entity's delete time each time you call soft-delete of entity manager or repository. You don't need to set this column - it will be automatically set. If the @DeleteDateColumn is set, the default scope will be "non-deleted". + * `@VersionColumn` is a special column that is automatically set to the version of the entity (incremental number) each time you call `save` of entity manager or repository. You don't need to set this column - it will be automatically set. @@ -289,6 +291,8 @@ or @Column({ type: "int", width: 200 }) ``` +> Note about `bigint` type: `bigint` column type, used in SQL databases, doesn't fit into the regular `number` type and maps property to a `string` instead. + ### Column types for `mysql` / `mariadb` `bit`, `int`, `integer`, `tinyint`, `smallint`, `mediumint`, `bigint`, `float`, `double`, @@ -307,7 +311,7 @@ or `date`, `time`, `time without time zone`, `time with time zone`, `interval`, `bool`, `boolean`, `enum`, `point`, `line`, `lseg`, `box`, `path`, `polygon`, `circle`, `cidr`, `inet`, `macaddr`, `tsvector`, `tsquery`, `uuid`, `xml`, `json`, `jsonb`, `int4range`, `int8range`, `numrange`, -`tsrange`, `tstzrange`, `daterange`, `geometry`, `geography`, `cube` +`tsrange`, `tstzrange`, `daterange`, `geometry`, `geography`, `cube`, `ltree` ### Column types for `cockroachdb` diff --git a/docs/example-with-express.md b/docs/example-with-express.md index 8985d77260..e7e6b75d1e 100644 --- a/docs/example-with-express.md +++ b/docs/example-with-express.md @@ -78,31 +78,28 @@ node src/app.js You should see the, "Application is up and running" message in your console right after you run the application. You must compile your files each time you make a change. -Alternatively, you can setup watcher or install [ts-node](http://github.com/ts-node/ts-node) to avoid manual compilation each time. +Alternatively, you can setup watcher or install [ts-node](https://github.com/TypeStrong/ts-node) to avoid manual compilation each time. ## Adding Express to the application Let's add Express to our application. First, let's install the packages we need: ``` -npm i express body-parser @types/express @types/body-parser --save +npm i express @types/express --save ``` * `express` is the express engine itself. It allows us to create a web api -* `body-parser` is used to setup how express would handle body sent by a client * `@types/express` is used to have a type information when using express -* `@types/body-parser` is used to have a type information when using body parser Let's edit the `src/app.ts` file and add express-related logic: ```typescript import * as express from "express"; import {Request, Response} from "express"; -import * as bodyParser from "body-parser"; // create and setup express app const app = express(); -app.use(bodyParser.json()); +app.use(express.json()); // register routes @@ -195,7 +192,6 @@ Let's change `src/app.ts`: ```typescript import * as express from "express"; import {Request, Response} from "express"; -import * as bodyParser from "body-parser"; import {createConnection} from "typeorm"; import {User} from "./entity/User"; @@ -205,7 +201,7 @@ createConnection().then(connection => { // create and setup express app const app = express(); - app.use(bodyParser.json()); + app.use(express.json()); // register routes diff --git a/docs/find-options.md b/docs/find-options.md index 8e924d6e4b..6827da32be 100644 --- a/docs/find-options.md +++ b/docs/find-options.md @@ -23,7 +23,7 @@ userRepository.find({ relations: ["profile", "photos", "videos", "videos.video_a * `join` - joins needs to be performed for the entity. Extended version of "relations". ```typescript -userRepository.find({ +userRepository.find({ join: { alias: "user", leftJoinAndSelect: { @@ -40,7 +40,7 @@ userRepository.find({ ```typescript userRepository.find({ where: { firstName: "Timber", lastName: "Saw" } }); ``` -Querying a column from an embedded entity should be done with respect to the hierarchy in which it was defined. Example: +Querying a column from an embedded entity should be done with respect to the hierarchy in which it was defined. Example: ```typescript userRepository.find({ where: { name: { first: "Timber", last: "Saw" } } }); @@ -57,7 +57,7 @@ userRepository.find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "user" WHERE ("firstName" = 'Timber' AND "lastName" = 'Saw') OR ("firstName" = 'Stan' AND "lastName" = 'Lee') @@ -66,7 +66,7 @@ SELECT * FROM "user" WHERE ("firstName" = 'Timber' AND "lastName" = 'Saw') OR (" * `order` - selection order. ```typescript -userRepository.find({ +userRepository.find({ order: { name: "ASC", id: "DESC" @@ -79,7 +79,7 @@ userRepository.find({ * `skip` - offset (paginated) from where entities should be taken. ```typescript -userRepository.find({ +userRepository.find({ skip: 5 }); ``` @@ -87,7 +87,7 @@ userRepository.find({ * `take` - limit (paginated) - max number of entities that should be taken. ```typescript -userRepository.find({ +userRepository.find({ take: 10 }); ``` @@ -95,12 +95,12 @@ userRepository.find({ ** If you are using typeorm with MSSQL, and want to use `take` or `limit`, you need to use order as well or you will receive the following error: `'Invalid usage of the option NEXT in the FETCH statement.'` ```typescript -userRepository.find({ - order: { - columnName: 'ASC' - }, - skip: 0, - take: 10 +userRepository.find({ + order: { + columnName: 'ASC' + }, + skip: 0, + take: 10 }) ``` @@ -120,7 +120,7 @@ userRepository.find({ ``` or ```ts -{ mode: "pessimistic_read"|"pessimistic_write"|"dirty_read" } +{ mode: "pessimistic_read"|"pessimistic_write"|"dirty_read"|"pessimistic_partial_write"|"pessimistic_write_or_fail" } ``` for example: @@ -131,15 +131,17 @@ userRepository.findOne(1, { }) ``` +`pessimistic_partial_write` and `pessimistic_write_or_fail` are supported only on Postgres and are equivalents of `SELECT .. FOR UPDATE SKIP LOCKED` and `SELECT .. FOR UPDATE NOWAIT`, accordingly. + Complete example of find options: ```typescript -userRepository.find({ +userRepository.find({ select: ["firstName", "lastName"], relations: ["profile", "photos", "videos"], - where: { - firstName: "Timber", - lastName: "Saw" + where: { + firstName: "Timber", + lastName: "Saw" }, order: { name: "ASC", @@ -166,7 +168,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }) ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "title" != 'About #1' @@ -182,7 +184,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "likes" < 10 @@ -198,7 +200,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "likes" <= 10 @@ -214,7 +216,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "likes" > 10 @@ -230,7 +232,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "likes" >= 10 @@ -246,7 +248,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "title" = 'About #2' @@ -262,7 +264,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "title" LIKE '%out #%' @@ -294,7 +296,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "likes" BETWEEN 1 AND 10 @@ -310,7 +312,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "title" IN ('About #2','About #3') @@ -326,7 +328,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query (Postgres notation): +will execute following query (Postgres notation): ```sql SELECT * FROM "post" WHERE "title" = ANY(['About #2','About #3']) @@ -342,7 +344,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "title" IS NULL @@ -358,7 +360,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "likes" = "dislikes" - 4 @@ -375,7 +377,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE "currentDate" > NOW() @@ -395,7 +397,7 @@ const loadedPosts = await connection.getRepository(Post).find({ }); ``` -will execute following query: +will execute following query: ```sql SELECT * FROM "post" WHERE NOT("likes" > 10) AND NOT("title" = 'About #2') diff --git a/docs/index.md b/docs/index.md index 434ddea5d5..5ecf31fdc0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ # Documentation This directory contains all TypeORM documentation. -This documentation is represented on a site. \ No newline at end of file +This documentation is [the TypeORM website](https://typeorm.io/) diff --git a/docs/logging.md b/docs/logging.md index 97e70da3a0..6c48fad29f 100644 --- a/docs/logging.md +++ b/docs/logging.md @@ -162,6 +162,6 @@ postRepository.save(post, { data: { request: request } }); // in logger you can access it this way: logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner) { const requestUrl = queryRunner && queryRunner.data["request"] ? "(" + queryRunner.data["request"].url + ") " : ""; - console.log(requestUrl + "executing query: " + sql); + console.log(requestUrl + "executing query: " + query); } ``` diff --git a/docs/many-to-many-relations.md b/docs/many-to-many-relations.md index ce522a43a6..10a53f3e95 100644 --- a/docs/many-to-many-relations.md +++ b/docs/many-to-many-relations.md @@ -69,6 +69,7 @@ This example will produce following tables: +-------------+--------------+----------------------------+ | id | int(11) | PRIMARY KEY AUTO_INCREMENT | | title | varchar(255) | | +| text | varchar(255) | | +-------------+--------------+----------------------------+ +-------------+--------------+----------------------------+ @@ -115,6 +116,45 @@ await connection.manager.save(question) This will only remove the record in the join table. The `question` and `categoryToRemove` records will still exist. +## Soft Deleting a relationship with cascade + +This example show what the cascading soft deletes behaves + +```typescript +const category1 = new Category(); +category1.name = "animals"; + +const category2 = new Category(); +category2.name = "zoo"; + +const question = new Question(); +question.categories = [category1, category2]; +const newQuestion = await connection.manager.save(question); + +await connection.manager.softRemove(newQuestion); +``` + +As you can see in this example we did not call save or softRemove for category1 and category2. But They will be automatically saved and soft-deleted when the cascade of relation options is set to true like this: + +```typescript +import {Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable} from "typeorm"; +import {Category} from "./Category"; + +@Entity() +export class Question { + + @PrimaryGeneratedColumn() + id: number; + + @ManyToMany(type => Category, category => category.questions, { + cascade: true + }) + @JoinTable() + categories: Category[]; + +} +``` + ## Loading many-to-many relations To load question with categories inside you must specify relation in `FindOptions`: @@ -134,7 +174,7 @@ const questions = await connection .getMany(); ``` -With eager loading enabled on a relation you don't have to specify relation or join it - it will ALWAYS be loaded automatically. +When using `FindOptions` you don't need to specify eager relations - they are always automatically loaded. ## bi-directional relations @@ -201,7 +241,7 @@ const categoriesWithQuestions = await connection ## many-to-many relations with custom properties -In case you need to have additional properties to your many-to-many relationship you have to create a new entity yourself. +In case you need to have additional properties to your many-to-many relationship you have to create a new entity yourself. For example if you would like entities `Post` and `Category` to have a many-to-many relationship with additional `order` column, you need to create entity `PostToCategory` with two `ManyToOne` relations pointing in both directions and custom columns in it: ```typescript @@ -216,10 +256,10 @@ export class PostToCategory { @Column() public postId!: number; - + @Column() public categoryId!: number; - + @Column() public order!: number; diff --git a/docs/many-to-one-one-to-many-relations.md b/docs/many-to-one-one-to-many-relations.md index 0a4e53d73e..16c24e2383 100644 --- a/docs/many-to-one-one-to-many-relations.md +++ b/docs/many-to-one-one-to-many-relations.md @@ -102,7 +102,7 @@ photo2.user = user; await connection.manager.save(photo2); ``` -With cascades enabled you can save this relation with only one `save` call. +With [cascades](https://github.com/typeorm/typeorm/blob/master/docs/relations.md#cascades) enabled you can save this relation with only one `save` call. To load a user with photos inside you must specify the relation in `FindOptions`: diff --git a/docs/migrations.md b/docs/migrations.md index a81db58271..3e4799d205 100644 --- a/docs/migrations.md +++ b/docs/migrations.md @@ -4,6 +4,7 @@ * [Creating a new migration](#creating-a-new-migration) * [Running and reverting migrations](#running-and-reverting-migrations) * [Generating migrations](#generating-migrations) +* [Connection option](#connection-option) * [Using migration API to write migrations](#using-migration-api-to-write-migrations) ## How migrations work @@ -86,7 +87,7 @@ typeorm migration:create -n PostRefactoring ``` Here, `PostRefactoring` is the name of the migration - you can specify any name you want. -After you run the command you can see a new file generated in the "migration" directory +After you run the command you can see a new file generated in the "migration" directory named `{TIMESTAMP}-PostRefactoring.ts` where `{TIMESTAMP}` is the current timestamp when the migration was generated. Now you can open the file and add your migration sql queries there. @@ -143,7 +144,7 @@ Once you have a migration to run on production, you can run them using a CLI com typeorm migration:run ``` -**`typeorm migration:create` and `typeorm migration:generate` will create `.ts` files. The `migration:run` and `migration:revert` commands only work on `.js` files. Thus the typescript files need to be compiled before running the commands.** Alternatively you can use `ts-node` in conjunction with `typeorm` to run `.ts` migration files. +**`typeorm migration:create` and `typeorm migration:generate` will create `.ts` files. The `migration:run` and `migration:revert` commands only work on `.js` files. Thus the typescript files need to be compiled before running the commands.** Alternatively you can use `ts-node` in conjunction with `typeorm` to run `.ts` migration files. Example with `ts-node`: ``` @@ -160,8 +161,8 @@ If for some reason you want to revert the changes, you can run: typeorm migration:revert ``` -This command will execute `down` in the latest executed migration. -If you need to revert multiple migrations you must call this command multiple times. +This command will execute `down` in the latest executed migration. +If you need to revert multiple migrations you must call this command multiple times. ## Generating migrations @@ -194,7 +195,13 @@ export class PostRefactoringTIMESTAMP implements MigrationInterface { ``` See, you don't need to write the queries on your own. -The rule of thumb for generating migrations is that you generate them after "each" change you made to your models. +The rule of thumb for generating migrations is that you generate them after "each" change you made to your models. To apply multi-line formatting to your generated migration queries, use the `p` (alias for `--pretty`) flag. + +## Connection option +If you need to run/revert your migrations for another connection rather than the default, use the `-c` (alias for `--connection`) and pass the config name as an argument +``` +typeorm -c migration:{run|revert} +``` ## Using migration API to write migrations @@ -239,6 +246,11 @@ export class QuestionRefactoringTIMESTAMP implements MigrationInterface { { name: "name", type: "varchar", + }, + { + name: 'created_at', + type: 'timestamp', + default: 'now()' } ] }), true); @@ -376,7 +388,7 @@ Drops database. createSchema(schemaPath: string, ifNotExist?: boolean): Promise ``` -- `schemaPath` - schema name. For SqlServer can accept schema path (e.g. 'dbName.schemaName') as parameter. +- `schemaPath` - schema name. For SqlServer can accept schema path (e.g. 'dbName.schemaName') as parameter. If schema path passed, it will create schema in specified database - `ifNotExist` - skips creation if `true`, otherwise throws error if schema already exist @@ -388,7 +400,7 @@ Creates a new table schema. dropSchema(schemaPath: string, ifExist?: boolean, isCascade?: boolean): Promise ``` -- `schemaPath` - schema name. For SqlServer can accept schema path (e.g. 'dbName.schemaName') as parameter. +- `schemaPath` - schema name. For SqlServer can accept schema path (e.g. 'dbName.schemaName') as parameter. If schema path passed, it will drop schema in specified database - `ifExist` - skips deletion if `true`, otherwise throws error if schema was not found - `isCascade` - If `true`, automatically drop objects (tables, functions, etc.) that are contained in the schema. diff --git a/docs/mongodb.md b/docs/mongodb.md index f8437b9d82..d3b26ed775 100644 --- a/docs/mongodb.md +++ b/docs/mongodb.md @@ -266,6 +266,35 @@ const timber = await userRepository.find({ }); ``` +Querying subdocuments + +```typescript +import {getMongoRepository} from "typeorm"; + +const userRepository = getMongoRepository(User); +// Query users with education Tree School +const users = await userRepository.find({ + where: { + 'profile.education': { $eq: "Tree School"} + } +}); +``` + +Querying Array of subdocuments + +```typescript +import {getMongoRepository} from "typeorm"; + +const userRepository = getMongoRepository(User); +// Query users with photos of size less than 500 +const users = await userRepository.find({ + where: { + 'photos.size': { $lt: 500} + } +}); + +``` + Both `MongoEntityManager` and `MongoRepository` contain lot of useful MongoDB-specific methods: @@ -309,7 +338,7 @@ Delete a document on MongoDB. #### `distinct` -The distinct command returns returns a list of distinct values for the given key across a collection. +The distinct command returns a list of distinct values for the given key across a collection. #### `dropCollectionIndex` diff --git a/docs/one-to-one-relations.md b/docs/one-to-one-relations.md index acb87e0bf6..ee5c86774f 100644 --- a/docs/one-to-one-relations.md +++ b/docs/one-to-one-relations.md @@ -82,7 +82,7 @@ user.profile = profile; await connection.manager.save(user); ``` -With cascades enabled you can save this relation with only one `save` call. +With [cascades](https://github.com/typeorm/typeorm/blob/master/docs/relations.md#cascades) enabled you can save this relation with only one `save` call. To load user with profile inside you must specify relation in `FindOptions`: diff --git a/docs/relational-query-builder.md b/docs/relational-query-builder.md index 247c41a576..0e2e69a98b 100644 --- a/docs/relational-query-builder.md +++ b/docs/relational-query-builder.md @@ -3,7 +3,6 @@ `RelationQueryBuilder` is a special type of `QueryBuilder` which allows you to work with your relations. Using it, you can bind entities to each other in the database without the need to load any entities, or you can load related entities easily. -Examples: For example, we have a `Post` entity and it has a many-to-many relation to `Category` called `categories`. Let's add a new category to this many-to-many relation: diff --git a/docs/relations-faq.md b/docs/relations-faq.md index 2eb89327de..8ae6469c9f 100644 --- a/docs/relations-faq.md +++ b/docs/relations-faq.md @@ -9,7 +9,7 @@ Self-referencing relations are relations which have a relation to themself. This is useful when you are storing entities in a tree-like structures. -Also "adjacency list" pattern is implemented used self-referenced relations. +Also "adjacency list" pattern is implemented using self-referenced relations. For example, you want to create categories tree in your application. Categories can nest categories, nested categories can nest other categories, etc. Self-referencing relations come handy here. diff --git a/docs/repository-api.md b/docs/repository-api.md index 00a3d6fd7f..22c84794be 100644 --- a/docs/repository-api.md +++ b/docs/repository-api.md @@ -51,7 +51,7 @@ const users = await repository } ``` -* `getId` - Gets the primary column property values of the given entity. +* `getId` - Gets the primary column property values of the given entity. If entity has composite primary keys then the returned value will be an object with names and values of primary columns. ```typescript @@ -135,12 +135,12 @@ await repository.insert({ }); -await manager.insert(User, [{ - firstName: "Foo", - lastName: "Bar" -}, { - firstName: "Rizz", - lastName: "Rak" +await manager.insert(User, [{ + firstName: "Foo", + lastName: "Bar" +}, { + firstName: "Rizz", + lastName: "Rak" }]); ``` @@ -162,6 +162,27 @@ await repository.delete([1, 2, 3]); await repository.delete({ firstName: "Timber" }); ``` +* `softDelete` and `restore` - Soft deleting and restoring a row by id + +```typescript +const repository = connection.getRepository(Entity); +// Delete a entity +await repository.softDelete(1); +// And You can restore it using restore; +await repository.restore(1); +``` + +* `softRemove` and `recover` - This is alternative to `softDelete` and `restore`. +```typescript +// You can soft-delete them using softRemove +const entities = await repository.find(); +const entitiesAfterSoftRemove = await repository.softRemove(entities); + +// And You can recover them using recover; +await repository.recover(entitiesAfterSoftRemove); +``` + + * `count` - Counts entities that match given options. Useful for pagination. ```typescript diff --git a/docs/select-query-builder.md b/docs/select-query-builder.md index 176af84e66..ba590c2d39 100644 --- a/docs/select-query-builder.md +++ b/docs/select-query-builder.md @@ -3,7 +3,7 @@ * [What is `QueryBuilder`](#what-is-querybuilder) * [How to create and use a `QueryBuilder`](#how-to-create-and-use-a-querybuilder) * [Getting values using QueryBuilder](#getting-values-using-querybuilder) -* [What are aliases for?](#what-are-aliases-for?) +* [What are aliases for?](#what-are-aliases-for) * [Using parameters to escape data](#using-parameters-to-escape-data) * [Adding `WHERE` expression](#adding-where-expression) * [Adding `HAVING` expression](#adding-having-expression) @@ -204,7 +204,7 @@ const photosSums = await getRepository(User) .createQueryBuilder("user") .select("user.id") .addSelect("SUM(user.photosCount)", "sum") - .where("user.id = :id", { id: 1 }) + .groupBy("user.id") .getRawMany(); // result will be like this: [{ id: 1, sum: 25 }, { id: 2, sum: 13 }, ...] @@ -342,7 +342,7 @@ createQueryBuilder("user") Which will produce the following SQL query: ```sql -SELECT ... FROM users user WHERE user.firstName IN (1, 2, 3, 4) +SELECT ... FROM users user WHERE user.id IN (1, 2, 3, 4) ``` @@ -776,7 +776,7 @@ const photosSums = await getRepository(User) .createQueryBuilder("user") .select("user.id") .addSelect("SUM(user.photosCount)", "sum") - .where("user.id = :id", { id: 1 }) + .groupBy("user.id") .getRawMany(); // result will be like this: [{ id: 1, sum: 25 }, { id: 2, sum: 13 }, ...] diff --git a/docs/support.md b/docs/support.md index d69707290a..aaf7229434 100644 --- a/docs/support.md +++ b/docs/support.md @@ -6,11 +6,11 @@ If you found a bug, issue, or you just want to propose a new feature, create [an ### Have a question? -If you have a question, you can ask it on [StackOverflow](https://stackoverflow.com/questions/tagged/typeorm). +If you have a question, you can ask it on [StackOverflow](https://stackoverflow.com/questions/tagged/typeorm) or other community support channels. ### Want community support? -If you want community support, or simply want to chat with friendly TypeORM enthusiasts and users, you can do it on [Slack](https://join.slack.com/t/typeorm/shared_invite/enQtNDQ1MzA3MDA5MTExLTFiNDEyOGUxZGQyYWIwOTA0NDQxODdkOGQ0OTUxNzFjYjUwY2E0ZmFlODc5OTYyYzAzNGM3MGZjYzhjYTBiZTY). +If you want community support, or simply want to chat with friendly TypeORM enthusiasts and users, you can do it on [Slack](https://join.slack.com/t/typeorm/shared_invite/zt-gej3gc00-hR~L~DqGUJ7qOpGy4SSq3g). ### Want professional commercial support? diff --git a/docs/supported-platforms.md b/docs/supported-platforms.md index 344e63f5d7..ec817e6e84 100644 --- a/docs/supported-platforms.md +++ b/docs/supported-platforms.md @@ -31,7 +31,7 @@ plugins: [ ] ``` -and make sure (sql-wasm.wasm)[https://github.com/sql-js/sql.js/blob/master/README.md#downloadingusing] file exists in your public path. +and make sure [sql-wasm.wasm file](https://github.com/sql-js/sql.js/blob/master/README.md#downloadingusing) exists in your public path. **Example of configuration** @@ -61,7 +61,7 @@ You have the option to choose between module loaders just like in browser packag For an example how to use TypeORM in Cordova see [typeorm/cordova-example](https://github.com/typeorm/cordova-example) and for Ionic see [typeorm/ionic-example](https://github.com/typeorm/ionic-example). **Important**: For use with Ionic, a custom webpack config file is needed! Please checkout the example to see the needed changes. ## React Native -TypeORM is able to on React Native apps using the [react-native-sqlite-storage](https://github.com/andpor/react-native-sqlite-storage) plugin. For an example see [typeom/react-native-example](https://github.com/typeorm/react-native-example). +TypeORM is able to run on React Native apps using the [react-native-sqlite-storage](https://github.com/andpor/react-native-sqlite-storage) plugin. For an example see [typeorm/react-native-example](https://github.com/typeorm/react-native-example). ## Expo diff --git a/docs/transactions.md b/docs/transactions.md index 0c03fb6efe..92f1788c2d 100644 --- a/docs/transactions.md +++ b/docs/transactions.md @@ -150,7 +150,7 @@ try { } catch (err) { - // since we have errors lets rollback changes we made + // since we have errors let's rollback changes we made await queryRunner.rollbackTransaction(); } finally { diff --git a/docs/using-cli.md b/docs/using-cli.md index 56b9f5aaa4..a240a9bf9d 100644 --- a/docs/using-cli.md +++ b/docs/using-cli.md @@ -5,7 +5,7 @@ * [Create a new entity](#create-a-new-entity) * [Create a new subscriber](#create-a-new-subscriber) * [Create a new migration](#create-a-new-migration) -* [Generate a migration from existing table schema](#generate-a-migration-from-exist-table-schema) +* [Generate a migration from existing table schema](#generate-a-migration-from-existing-table-schema) * [Run migrations](#run-migrations) * [Revert migrations](#revert-migrations) * [Show migrations](#show-migrations) @@ -37,10 +37,12 @@ Add typeorm command under scripts section in package.json ``` "scripts" { ... - "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js" + "typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js" } ``` +If you want to load more modules like [module-alias](https://github.com/ilearnio/module-alias) you can add more `--require my-module-supporting-register` + Then you may run the command like this: ``` npm run typeorm migration:run diff --git a/docs/using-ormconfig.md b/docs/using-ormconfig.md index 49f1271c08..1f95b39354 100644 --- a/docs/using-ormconfig.md +++ b/docs/using-ormconfig.md @@ -101,37 +101,36 @@ TYPEORM_ENTITIES = entity/*.js,modules/**/entity/*.js List of available env variables you can set: +* TYPEORM_CACHE +* TYPEORM_CACHE_ALWAYS_ENABLED +* TYPEORM_CACHE_DURATION +* TYPEORM_CACHE_OPTIONS * TYPEORM_CONNECTION -* TYPEORM_HOST -* TYPEORM_USERNAME -* TYPEORM_PASSWORD * TYPEORM_DATABASE -* TYPEORM_PORT -* TYPEORM_URL -* TYPEORM_SID -* TYPEORM_SCHEMA -* TYPEORM_SYNCHRONIZE +* TYPEORM_DEBUG +* TYPEORM_DRIVER_EXTRA * TYPEORM_DROP_SCHEMA -* TYPEORM_MIGRATIONS_RUN -* TYPEORM_MIGRATIONS_TRANSACTION_MODE * TYPEORM_ENTITIES -* TYPEORM_MIGRATIONS -* TYPEORM_MIGRATIONS_TABLE_NAME -* TYPEORM_SUBSCRIBERS -* TYPEORM_ENTITY_SCHEMAS -* TYPEORM_LOGGING -* TYPEORM_LOGGER +* TYPEORM_ENTITIES_DIR * TYPEORM_ENTITY_PREFIX +* TYPEORM_HOST +* TYPEORM_LOGGER +* TYPEORM_LOGGING * TYPEORM_MAX_QUERY_EXECUTION_TIME -* TYPEORM_ENTITIES_DIR +* TYPEORM_MIGRATIONS * TYPEORM_MIGRATIONS_DIR +* TYPEORM_MIGRATIONS_RUN +* TYPEORM_MIGRATIONS_TABLE_NAME +* TYPEORM_PASSWORD +* TYPEORM_PORT +* TYPEORM_SCHEMA +* TYPEORM_SID +* TYPEORM_SUBSCRIBERS * TYPEORM_SUBSCRIBERS_DIR -* TYPEORM_DRIVER_EXTRA -* TYPEORM_DEBUG -* TYPEORM_CACHE -* TYPEORM_CACHE_OPTIONS -* TYPEORM_CACHE_ALWAYS_ENABLED -* TYPEORM_CACHE_DURATION +* TYPEORM_SYNCHRONIZE +* TYPEORM_URL +* TYPEORM_USERNAME +* TYPEORM_UUID_EXTENSION `TYPEORM_CACHE` should be boolean or string of cache type @@ -211,7 +210,7 @@ Note that Typeorm will use the first valid method found and will not load the ot ## Overriding options defined in ormconfig Sometimes you want to override values defined in your ormconfig file, -or you might to append some TypeScript / JavaScript logic to your configuration. +or you might want to append some TypeScript / JavaScript logic to your configuration. In such cases you can load options from ormconfig and get `ConnectionOptions` built, then you can do whatever you want with those options, before passing them to `createConnection` function: diff --git a/docs/zh_CN/README.md b/docs/zh_CN/README.md index 348588f0a3..c8e24aeee8 100644 --- a/docs/zh_CN/README.md +++ b/docs/zh_CN/README.md @@ -4,8 +4,8 @@

- - + + diff --git a/docs/zh_CN/connection-options.md b/docs/zh_CN/connection-options.md index 3966d6c8e8..5523bc6afb 100644 --- a/docs/zh_CN/connection-options.md +++ b/docs/zh_CN/connection-options.md @@ -5,6 +5,7 @@ - [`mysql`/`mariadb`](#mysql/mariadb) - [`postgres`/`cockroachdb`连接选项](#postgres/cockroachdb连接选项) - [`sqlite`](#sqlite) + - [`better-sqlite3`](#better-sqlite3) - [`cordova`](#cordova) - [`react-native`](#react-native) - [`nativescript`](#nativescript) @@ -20,7 +21,7 @@ ## 常用的连接选项 -- `type` - 数据库类型。你必须指定要使用的数据库引擎。该值可以是"mysql","postgres","mariadb","sqlite","cordova","nativescript","oracle","mssql","mongodb","sqljs","react-native"。此选项是**必需**的。 +- `type` - 数据库类型。你必须指定要使用的数据库引擎。该值可以是"mysql","postgres","mariadb","sqlite", "better-sqlite3","cordova","nativescript","oracle","mssql","mongodb","sqljs","react-native"。此选项是**必需**的。 - `name` - 连接名。 在使用 `getConnection(name: string)` 或 `ConnectionManager.get(name: string)`时候需要用到。不同连接的连接名称不能相同,它们都必须是唯一的。如果没有给出连接名称,那么它将被设置为"default"。 @@ -128,6 +129,14 @@ - `database` - 数据库路径。 例如 "./mydb.sql" +## `better-sqlite3` + +* `database` - 数据库路径。 例如 "./mydb.sql" + +* `statementCacheSize` - Sqlite 查询 Statement 缓存大小。默认100 + +* `prepareDatabase` - 在数据库投入使用前运行的函数。你可以在这里访问到better-sqlite3原始数据库对象。 + ## `cordova` - `database` - 数据库名 diff --git a/docs/zh_CN/connection.md b/docs/zh_CN/connection.md index b6369f4c5c..416729adc4 100644 --- a/docs/zh_CN/connection.md +++ b/docs/zh_CN/connection.md @@ -87,7 +87,7 @@ const secondConnection: Connection = await createConnection("test2-connection"); const connections: Connection[] = await createConnections(); ``` -不同的连接必须具有不同的名称默。认情况下,如果未指定连接名称,则为`default`。 +不同的连接必须具有不同的名称。默认情况下,如果未指定连接名称,则为`default`。 通常在你使用多个数据库或多个连接配置时才会使用多连接。 创建连接后,你可以使用`getConnection`函数从应用程序中的任何位置使用它: diff --git a/docs/zh_CN/index.md b/docs/zh_CN/index.md index ea48fa264c..6d6893d0d4 100644 --- a/docs/zh_CN/index.md +++ b/docs/zh_CN/index.md @@ -4,8 +4,8 @@

- - + + diff --git a/docs/zh_CN/using-ormconfig.md b/docs/zh_CN/using-ormconfig.md index 269869b904..e8a8965404 100644 --- a/docs/zh_CN/using-ormconfig.md +++ b/docs/zh_CN/using-ormconfig.md @@ -100,31 +100,36 @@ TYPEORM_ENTITIES = entity/.*js,modules/**/entity/.*js 可以设置的可用 env 变量列表: +- TYPEORM_CACHE +- TYPEORM_CACHE_ALWAYS_ENABLED +- TYPEORM_CACHE_DURATION +- TYPEORM_CACHE_OPTIONS - TYPEORM_CONNECTION -- TYPEORM_HOST -- TYPEORM_USERNAME -- TYPEORM_PASSWORD - TYPEORM_DATABASE -- TYPEORM_PORT -- TYPEORM_URL -- TYPEORM_SID -- TYPEORM_SCHEMA -- TYPEORM_SYNCHRONIZE +- TYPEORM_DEBUG +- TYPEORM_DRIVER_EXTRA - TYPEORM_DROP_SCHEMA -- TYPEORM_MIGRATIONS_RUN -- TYPEORM_MIGRATIONS_TRANSACTION_MODE - TYPEORM_ENTITIES -- TYPEORM_MIGRATIONS -- TYPEORM_SUBSCRIBERS -- TYPEORM_ENTITY_SCHEMAS -- TYPEORM_LOGGING -- TYPEORM_LOGGER +- TYPEORM_ENTITIES_DIR - TYPEORM_ENTITY_PREFIX +- TYPEORM_HOST +- TYPEORM_LOGGER +- TYPEORM_LOGGING - TYPEORM_MAX_QUERY_EXECUTION_TIME -- TYPEORM_ENTITIES_DIR +- TYPEORM_MIGRATIONS - TYPEORM_MIGRATIONS_DIR +- TYPEORM_MIGRATIONS_RUN +- TYPEORM_MIGRATIONS_TABLE_NAME +- TYPEORM_PASSWORD +- TYPEORM_PORT +- TYPEORM_SCHEMA +- TYPEORM_SID +- TYPEORM_SUBSCRIBERS - TYPEORM_SUBSCRIBERS_DIR -- TYPEORM_DRIVER_EXTRA +- TYPEORM_SYNCHRONIZE +- TYPEORM_URL +- TYPEORM_USERNAME +- TYPEORM_UUID_EXTENSION `ormconfig.env`只能在开发期间使用。在生产环境中,你可以在 ENVIRONMENT VARIABLES 中设置所有这些值。 diff --git a/extra/typeorm-class-transformer-shim.js b/extra/typeorm-class-transformer-shim.js index 5066687194..33b5dd9e25 100644 --- a/extra/typeorm-class-transformer-shim.js +++ b/extra/typeorm-class-transformer-shim.js @@ -59,12 +59,21 @@ function makePropertyDecorator(typeFunction) { // columns -/* export */ -function Column(typeOrOptions, options) { +/* export */ function Column(typeOrOptions, options) { return makePropertyDecorator(typeOrOptions); } exports.Column = Column; +/* export */ function ViewColumn(typeOrOptions, options) { + return makePropertyDecorator(typeOrOptions); +} +exports.ViewColumn = ViewColumn; + +/* export */ function DeleteDateColumn(options) { + return function(object, propertyName) {}; +} +exports.DeleteDateColumn = DeleteDateColumn; + /* export */ function CreateDateColumn(options) { return function(object, propertyName) {}; } @@ -192,6 +201,11 @@ exports.ChildEntity = ChildEntity; } exports.Entity = Entity; +/* export */ function ViewEntity(options) { + return function(object) {}; +} +exports.ViewEntity = ViewEntity; + /* export */ function TableInheritance(type) { return function(object) {}; } diff --git a/extra/typeorm-model-shim.js b/extra/typeorm-model-shim.js index 6de41344d3..e3a297be3d 100644 --- a/extra/typeorm-model-shim.js +++ b/extra/typeorm-model-shim.js @@ -29,6 +29,18 @@ } exports.Column = Column; +/* export */ function ViewColumn(typeOrOptions, options) { + return function (object, propertyName) { + }; +} +exports.ViewColumn = ViewColumn; + +/* export */ function DeleteDateColumn(options) { + return function (object, propertyName) { + }; +} +exports.DeleteDateColumn = DeleteDateColumn; + /* export */ function CreateDateColumn(options) { return function (object, propertyName) { }; @@ -79,6 +91,12 @@ exports.ChildEntity = ChildEntity; } exports.Entity = Entity; +/* export */ function ViewEntity(name, options) { + return function (object) { + }; +} +exports.ViewEntity = ViewEntity; + /* export */ function TableInheritance(type) { return function (object) { }; diff --git a/gulpfile.ts b/gulpfile.ts index de3dfcf177..7d0fbeb05d 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -11,7 +11,7 @@ const replace = require("gulp-replace"); const rename = require("gulp-rename"); const mocha = require("gulp-mocha"); const chai = require("chai"); -const tslint = require("gulp-tslint"); +const eslint = require("gulp-eslint"); const sourcemaps = require("gulp-sourcemaps"); const istanbul = require("gulp-istanbul"); const remapIstanbul = require("remap-istanbul/lib/gulpRemapIstanbul"); @@ -70,6 +70,15 @@ export class Gulpfile { .pipe(gulp.dest("./build/browser/src")); } + /** + * Replaces PlatformTools with browser-specific implementation called BrowserPlatformTools. + */ + @Task() + browserCopyDirectoryExportedClassesLoader() { + return gulp.src("./src/platform/BrowserDirectoryExportedClassesLoader.template") + .pipe(rename("BrowserDirectoryExportedClassesLoader.ts")) + .pipe(gulp.dest("./build/browser/src/platform")); + } /** * Replaces PlatformTools with browser-specific implementation called BrowserPlatformTools. */ @@ -97,7 +106,10 @@ export class Gulpfile { "lib": ["es5", "es6", "dom"], typescript: require("typescript") }); - const tsResult = gulp.src(["./build/browser/src/**/*.ts", "./node_modules/reflect-metadata/**/*.d.ts", "./node_modules/@types/**/*.ts"]) + const tsResult = gulp.src([ + "./build/browser/src/**/*.ts", + "./node_modules/reflect-metadata/**/*.d.ts" + ]) .pipe(sourcemaps.init()) .pipe(tsProject()); @@ -151,8 +163,7 @@ export class Gulpfile { typescript: require("typescript") }); const tsResult = gulp.src([ - "./src/**/*.ts", - "./node_modules/@types/**/*.ts", + "./src/**/*.ts" ]) .pipe(sourcemaps.init()) .pipe(tsProject()); @@ -231,7 +242,7 @@ export class Gulpfile { package() { return [ "clean", - ["browserCopySources", "browserCopyPlatformTools", "browserCopyDisabledDriversDummy"], + ["browserCopySources", "browserCopyPlatformTools", "browserCopyDisabledDriversDummy", "browserCopyDirectoryExportedClassesLoader"], ["packageCompile", "browserCompile"], "packageMoveCompiledFiles", [ @@ -269,18 +280,11 @@ export class Gulpfile { * Runs ts linting to validate source code. */ @Task() - tslint() { + eslint() { return gulp.src(["./src/**/*.ts", "./test/**/*.ts", "./sample/**/*.ts"]) - .pipe( - tslint({ - formatter: "stylish" - }) - ) - .pipe(tslint.report({ - emitError: true, - sort: true, - bell: true - })); + .pipe(eslint()) + .pipe(eslint.format('stylish')) + .pipe(eslint.failAfterError()) } /** diff --git a/ormconfig.circleci-cockroach.json b/ormconfig.circleci-cockroach.json deleted file mode 100644 index b91014a781..0000000000 --- a/ormconfig.circleci-cockroach.json +++ /dev/null @@ -1,92 +0,0 @@ -[ - { - "skip": true, - "name": "mysql", - "type": "mysql", - "host": "localhost", - "port": 3306, - "username": "root", - "password": "admin", - "database": "test" - }, - { - "skip": true, - "name": "mariadb", - "type": "mariadb", - "host": "mariadb", - "port": 3306, - "username": "root", - "password": "admin", - "database": "test" - }, - { - "skip": true, - "name": "sqlite", - "type": "sqlite", - "database": "temp/sqlitedb.db" - }, - { - "skip": true, - "name": "postgres", - "type": "postgres", - "host": "localhost", - "port": 5432, - "username": "test", - "password": "test", - "database": "test" - }, - { - "skip": true, - "name": "sqljs", - "type": "sqljs" - }, - { - "skip": true, - "name": "mssql", - "type": "mssql", - "host": "localhost", - "username": "sa", - "password": "Admin12345", - "database": "tempdb" - }, - { - "skip": true, - "name": "sap", - "type": "sap", - "host": "localhost", - "port": 39015, - "username": "SYSTEM", - "password": "HXEHana1", - "database": "HXE", - "logging": false - }, - { - "skip": true, - "disabledIfNotEnabledImplicitly": true, - "name": "mongodb", - "type": "mongodb", - "database": "test", - "useNewUrlParser": true, - "useUnifiedTopology": true - }, - { - "skip": false, - "name": "cockroachdb", - "type": "cockroachdb", - "host": "localhost", - "port": 26257, - "username": "root", - "password": "", - "database": "defaultdb" - }, - { - "skip": true, - "name": "oracle", - "type": "oracle", - "host": "localhost", - "username": "typeorm", - "password": "Passw0rd", - "port": 1521, - "sid": "orclpdb1.localdomain" - } -] diff --git a/ormconfig.circleci-common.json b/ormconfig.circleci-common.json index 286289f0f6..d9f558a78a 100644 --- a/ormconfig.circleci-common.json +++ b/ormconfig.circleci-common.json @@ -1,71 +1,89 @@ [ { - "skip": false, + "skip": true, "name": "mysql", "type": "mysql", - "host": "localhost", + "host": "typeorm-mysql", "port": 3306, "username": "root", "password": "admin", - "database": "test" + "database": "test", + "logging": false }, { - "skip": false, + "skip": true, "name": "mariadb", "type": "mariadb", - "host": "mariadb", + "host": "typeorm-mariadb", "port": 3306, "username": "root", "password": "admin", - "database": "test" + "database": "test", + "logging": false }, { - "skip": false, + "skip": true, "name": "sqlite", "type": "sqlite", - "database": "temp/sqlitedb.db" + "database": "temp/sqlitedb.db", + "logging": false }, { - "skip": false, + "skip": true, + "name": "better-sqlite3", + "type": "better-sqlite3", + "database": "temp/better-sqlite3db.db", + "logging": false + }, + { + "skip": true, "name": "postgres", "type": "postgres", - "host": "localhost", + "host": "typeorm-postgres", "port": 5432, "username": "test", "password": "test", - "database": "test" + "database": "test", + "logging": false }, { "skip": false, "name": "sqljs", - "type": "sqljs" + "type": "sqljs", + "logging": false }, + { "skip": true, "name": "mssql", "type": "mssql", - "host": "localhost", + "host": "typeorm-mssql", + "port": 1433, "username": "sa", "password": "Admin12345", - "database": "tempdb" + "database": "tempdb", + "logging": false }, { "skip": true, "name": "sap", "type": "sap", - "host": "localhost", + "host": "typeorm-hana", "port": 39015, "username": "SYSTEM", - "password": "HXEHana1", + "password": "MySuperHanaPwd123!", "database": "HXE", "logging": false }, { - "skip": false, + "skip": true, "disabledIfNotEnabledImplicitly": true, "name": "mongodb", "type": "mongodb", + "host": "typeorm-mongodb", + "port": 27017, "database": "test", + "logging": false, "useNewUrlParser": true, "useUnifiedTopology": true }, @@ -73,7 +91,7 @@ "skip": true, "name": "cockroachdb", "type": "cockroachdb", - "host": "localhost", + "host": "typeorm-cockroachdb", "port": 26257, "username": "root", "password": "", @@ -83,10 +101,14 @@ "skip": true, "name": "oracle", "type": "oracle", - "host": "localhost", - "username": "typeorm", - "password": "Passw0rd", + "host": "typeorm-oracle", "port": 1521, - "sid": "orclpdb1.localdomain" + "sid": "XE", + "username": "system", + "password": "oracle", + "logging": false, + "extra": { + "connectString": "typeorm-oracle:1521/XE" + } } ] diff --git a/ormconfig.circleci-oracle.json b/ormconfig.circleci-oracle.json deleted file mode 100644 index 83bc38febe..0000000000 --- a/ormconfig.circleci-oracle.json +++ /dev/null @@ -1,92 +0,0 @@ -[ - { - "skip": true, - "name": "mysql", - "type": "mysql", - "host": "localhost", - "port": 3306, - "username": "root", - "password": "admin", - "database": "test" - }, - { - "skip": true, - "name": "mariadb", - "type": "mariadb", - "host": "mariadb", - "port": 3306, - "username": "root", - "password": "admin", - "database": "test" - }, - { - "skip": true, - "name": "sqlite", - "type": "sqlite", - "database": "temp/sqlitedb.db" - }, - { - "skip": true, - "name": "postgres", - "type": "postgres", - "host": "localhost", - "port": 5432, - "username": "test", - "password": "test", - "database": "test" - }, - { - "skip": true, - "name": "sqljs", - "type": "sqljs" - }, - { - "skip": true, - "name": "mssql", - "type": "mssql", - "host": "localhost", - "username": "sa", - "password": "Admin12345", - "database": "tempdb" - }, - { - "skip": true, - "name": "sap", - "type": "sap", - "host": "localhost", - "port": 39015, - "username": "SYSTEM", - "password": "HXEHana1", - "database": "HXE", - "logging": false - }, - { - "skip": true, - "disabledIfNotEnabledImplicitly": true, - "name": "mongodb", - "type": "mongodb", - "database": "test", - "useNewUrlParser": true, - "useUnifiedTopology": true - }, - { - "skip": true, - "name": "cockroachdb", - "type": "cockroachdb", - "host": "localhost", - "port": 26257, - "username": "root", - "password": "", - "database": "defaultdb" - }, - { - "skip": false, - "name": "oracle", - "type": "oracle", - "host": "localhost", - "username": "typeorm", - "password": "Passw0rd", - "port": 1521, - "sid": "orclpdb1.localdomain" - } -] diff --git a/ormconfig.json.dist b/ormconfig.json.dist index 07311e30b2..f855baf460 100644 --- a/ormconfig.json.dist +++ b/ormconfig.json.dist @@ -28,6 +28,13 @@ "database": "temp/sqlitedb.db", "logging": false }, + { + "skip": false, + "name": "better-sqlite3", + "type": "better-sqlite3", + "database": "temp/better-sqlite3db.db", + "logging": false + }, { "skip": false, "name": "postgres", @@ -90,5 +97,31 @@ "logging": false, "useNewUrlParser": true, "useUnifiedTopology": true + }, + { + "skip": true, + "name": "aurora-data-api", + "type": "aurora-data-api", + "region": "us-east-1", + "secretArn": "mysecret", + "resourceArn": "app-dbcluster", + "database": "app-dbcluster-mine", + "serviceConfigOptions": { + "maxRetries": 3 + }, + "logging": false + }, + { + "skip": true, + "name": "aurora-data-api-pg", + "type": "aurora-data-api-pg", + "region": "us-east-1", + "secretArn": "mysecret", + "resourceArn": "app-dbcluster", + "database": "app-dbcluster-mine", + "serviceConfigOptions": { + "maxRetries": 3 + }, + "logging": false } ] diff --git a/ormconfig.travis.json b/ormconfig.travis.json deleted file mode 100644 index f6a76e4c9c..0000000000 --- a/ormconfig.travis.json +++ /dev/null @@ -1,93 +0,0 @@ -[ - { - "skip": false, - "name": "mysql", - "type": "mysql", - "host": "localhost", - "port": 3306, - "username": "root", - "password": "admin", - "database": "test" - }, - { - "skip": false, - "name": "mariadb", - "type": "mariadb", - "host": "localhost", - "port": 3307, - "username": "root", - "password": "admin", - "database": "test" - }, - { - "skip": false, - "name": "sqlite", - "type": "sqlite", - "database": "temp/sqlitedb.db" - }, - { - "skip": false, - "name": "postgres", - "type": "postgres", - "host": "localhost", - "port": 5432, - "username": "test", - "password": "test", - "database": "test", - "logging": false - }, - { - "skip": false, - "name": "sqljs", - "type": "sqljs" - }, - { - "skip": false, - "name": "mssql", - "type": "mssql", - "host": "localhost", - "username": "sa", - "password": "Admin12345", - "database": "tempdb" - }, - { - "skip": true, - "name": "oracle", - "type": "oracle", - "host": "localhost", - "username": "system", - "password": "oracle", - "port": 1521, - "sid": "xe.oracle.docker" - }, - { - "skip": false, - "name": "cockroachdb", - "type": "cockroachdb", - "host": "localhost", - "port": 26257, - "username": "root", - "password": "", - "database": "defaultdb" - }, - { - "skip": true, - "name": "sap", - "type": "sap", - "host": "localhost", - "port": 39015, - "username": "SYSTEM", - "password": "HXEHana1", - "database": "HXE", - "logging": false - }, - { - "skip": false, - "disabledIfNotEnabledImplicitly": true, - "name": "mongodb", - "type": "mongodb", - "database": "test", - "useNewUrlParser": true, - "useUnifiedTopology": true - } -] diff --git a/package-lock.json b/package-lock.json index 1434bb6d64..22e4326e6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,9 @@ "dev": true }, "@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==", + "version": "1.8.15", + "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-1.8.15.tgz", + "integrity": "sha512-kIB71V3DcrA4iysBbOsYcxd4WWlOE7OFtCUYNfflPODM0lbIR23A236QeTn5iAeYwcHmMjR/TAKp5KQQh/WqoQ==", "dev": true, "requires": { "@types/tunnel": "0.0.0", @@ -38,22 +38,28 @@ } }, "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "dev": true, "requires": { - "@babel/highlight": "^7.8.3" + "@babel/highlight": "^7.10.4" } }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" }, "dependencies": { @@ -109,13 +115,36 @@ } } }, - "@babel/runtime": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.7.tgz", - "integrity": "sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==", + "@eslint/eslintrc": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz", + "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==", "dev": true, "requires": { - "regenerator-runtime": "^0.13.4" + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "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 + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } } }, "@gulp-sourcemaps/identity-map": { @@ -131,34 +160,19 @@ "through2": "^2.0.3" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "remove-trailing-separator": "^1.0.1" } }, "through2": { @@ -183,34 +197,13 @@ "through2": "^2.0.3" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "remove-trailing-separator": "^1.0.1" } }, "through2": { @@ -251,28 +244,19 @@ "fastq": "^1.6.0" } }, - "@samverschueren/stream-to-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", - "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", - "dev": true, - "requires": { - "any-observable": "^0.3.0" - } - }, "@sinonjs/commons": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.1.tgz", - "integrity": "sha512-Debi3Baff1Qu1Unc3mjJ96MgpbwTn43S1+9yJ0llWygPwDNu2aaWBD6yc9y/Z8XDRNhx7U+u2UDg2OGQXkclUQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", + "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/fake-timers": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.0.tgz", - "integrity": "sha512-atR1J/jRXvQAb47gfzSK8zavXy7BcpnYq21ALon0U99etu99vsir0trzIO3wpeLtW+LLVY6X7EkfVTbjGSH8Ww==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0" @@ -289,9 +273,9 @@ } }, "@sinonjs/samsam": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.0.3.tgz", - "integrity": "sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.1.0.tgz", + "integrity": "sha512-42nyaQOVunX5Pm6GRJobmzbS7iLI+fhERITnETXzzwDZh+TtDr/Au3yAvXVjFmZ4wEUaE4Y3NFZfKv0bV0cbtg==", "dev": true, "requires": { "@sinonjs/commons": "^1.6.0", @@ -305,16 +289,27 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@sqltools/formatter": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.2.tgz", + "integrity": "sha512-/5O7Fq6Vnv8L6ucmPjaWbVG1XkP4FO+w5glqfkIsq3Xw4oyNAdJddbnYodNDAfjVUvo/rrSCTom4kAND7T1o5Q==" + }, + "@types/app-root-path": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/app-root-path/-/app-root-path-1.2.4.tgz", + "integrity": "sha1-p4twMoKzKsVN52j1US7MNWmRncc=", + "dev": true + }, "@types/chai": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.10.tgz", - "integrity": "sha512-TlWWgb21+0LdkuFqEqfmy7NEgfB/7Jjux15fWQAh3P93gbmXuwTM/vxEdzW89APIcI2BgKR48yjeAkdeH+4qvQ==", + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.12.tgz", + "integrity": "sha512-aN5IAC8QNtSUdQzxu7lGBgYAOuU1tmRU4c9dIq5OKGf/SBVjXo+ffM2wEjudAWbgpOhy60nLoAGH1xm8fpCKFQ==", "dev": true }, "@types/chai-as-promised": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.2.tgz", - "integrity": "sha512-PO2gcfR3Oxa+u0QvECLe1xKXOqYTzCmWf0FhLhjREoW3fPAVamjihL7v1MOVLJLsnAMdLcjkfrs01yvDMwVK4Q==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.3.tgz", + "integrity": "sha512-FQnh1ohPXJELpKhzjuDkPLR2BZCAqed+a6xV4MI/T3XzHfd2FlarfUGUdZYgqYe8oxkYn0fchHEeHfHqdZ96sg==", "dev": true, "requires": { "@types/chai": "*" @@ -331,11 +326,14 @@ "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==", "dev": true }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true + "@types/dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw==", + "dev": true, + "requires": { + "dotenv": "*" + } }, "@types/expect": { "version": "1.20.4", @@ -343,19 +341,12 @@ "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", "dev": true }, - "@types/fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@types/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha512-mQjDxyOM1Cpocd+vm1kZBP7smwKZ4TNokFeds9LV7OZibmPJFEzY3+xZMrKfUdNT71lv8GoCPD6upKwHxubClw==", - "dev": true - }, "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", "dev": true, "requires": { - "@types/events": "*", "@types/minimatch": "*", "@types/node": "*" } @@ -381,6 +372,18 @@ "chokidar": "^2.1.2" } }, + "@types/js-yaml": { + "version": "3.12.5", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.5.tgz", + "integrity": "sha512-JCcp6J0GV66Y4ZMDAQCXot4xprYB+Zfd3meK9+INSJeVZwJmHAW30BBEEkPzXswMXuiyReUGOP3GxrADc9wPww==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, "@types/merge2": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@types/merge2/-/merge2-1.3.0.tgz", @@ -396,16 +399,37 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", "dev": true }, + "@types/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", + "dev": true + }, + "@types/mkdirp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.1.tgz", + "integrity": "sha512-HkGSK7CGAXncr8Qn/0VqNtExEE+PHMWb+qlR1faHMao7ng6P3tAaoWWBMdva0gL5h4zprjIO89GJOLXsMcDm1Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/mocha": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", - "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.0.3.tgz", + "integrity": "sha512-vyxR57nv8NfcU0GZu8EUXZLTbCMupIUwy95LJ6lllN+JRPG25CwMHoB1q5xKh8YKhQnHYRAn4yW2yuHbf/5xgg==", "dev": true }, "@types/node": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.0.tgz", - "integrity": "sha512-0ARSQootUG1RljH2HncpsY2TJBfGQIKOOi7kxzUY6z54ePu/ZD+wJA8zI2Q6v8rol2qpG/rvqsReco8zNMPvhQ==", + "version": "14.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.1.tgz", + "integrity": "sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ==", + "dev": true + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, "@types/parse-json": { @@ -415,9 +439,9 @@ "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==", + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.9.tgz", + "integrity": "sha512-sqsgQqFT7HmQz/V5jH1O0fvQQnXAJO46Gg9LRO/JPfjmVmGUlcx831TZZO3Y3HtWhIkzf3kTsNT0Z0kzIhIvZw==", "dev": true, "requires": { "@types/node": "*", @@ -425,9 +449,9 @@ } }, "@types/rimraf": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-2.0.3.tgz", - "integrity": "sha512-dZfyfL/u9l/oi984hEXdmAjX3JHry7TLWw43u1HQ8HhPv6KtfxnrZ3T/bleJ0GEvnk9t5sM7eePkgMqz3yBcGg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-3.0.0.tgz", + "integrity": "sha512-7WhJ0MdpFgYQPXlF4Dx+DhgvlPCfz/x5mHaeDQAKhcenvQP1KCpLQ18JklAqeGMYSAT2PxLpzd0g2/HE7fj7hQ==", "dev": true, "requires": { "@types/glob": "*", @@ -444,18 +468,27 @@ } }, "@types/sinon": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.5.2.tgz", - "integrity": "sha512-T+m89VdXj/eidZyejvmoP9jivXgBDdkOSBVQjU9kF349NEx10QdPNGxHeZUaj1IlJ32/ewdyXJjnJxyxJroYwg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.5.tgz", + "integrity": "sha512-4CnkGdM/5/FXDGqL32JQ1ttVrGvhOoesLLF7VnTh4KdjK5N5VQOtxaylFqqTjnHx55MnD9O02Nbk5c1ELC8wlQ==", + "dev": true, + "requires": { + "@types/sinonjs__fake-timers": "*" + } + }, + "@types/sinonjs__fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.1.tgz", + "integrity": "sha512-yYezQwGWty8ziyYLdZjwxyMb0CZR49h8JALHGrxjQHWlqGgc8kLdHEgWrgL0uZ29DMvEVBDnHU2Wg36zKSIUtA==", "dev": true }, "@types/source-map-support": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@types/source-map-support/-/source-map-support-0.5.1.tgz", - "integrity": "sha512-VDqnZe9D2zR19qbeRvwYyHSp7AtUtCkTaRVFQ8wzwH9TXw9kKKq/vBhfEnFEXVupO2M0lBMA9mr/XyQ6gEkUOA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@types/source-map-support/-/source-map-support-0.5.3.tgz", + "integrity": "sha512-fvjMjVH8Rmokw2dWh1dkj90iX5R8FPjeZzjNH+6eFXReh0QnHFf1YBl3B0CF0RohIAA3SDRJsGeeUWKl6d7HqA==", "dev": true, "requires": { - "@types/node": "*" + "source-map": "^0.6.0" } }, "@types/tunnel": { @@ -468,11 +501,12 @@ } }, "@types/undertaker": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.2.tgz", - "integrity": "sha512-j4iepCSuY2JGW/hShVtUBagic0klYNFIXP7VweavnYnNC2EjiKxJFeaS9uaJmAT0ty9sQSqTS1aagWMZMV0HyA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/undertaker/-/undertaker-1.2.3.tgz", + "integrity": "sha512-OhvIYx6pUJBxYZf5fM/BVMNXZQMy095kplml+4cWrlNqM1t6XtSIQCuVySGmICZCnzi69Epdljyplm86BlTouQ==", "dev": true, "requires": { + "@types/node": "*", "@types/undertaker-registry": "*" } }, @@ -503,10 +537,19 @@ "@types/vinyl": "*" } }, + "@types/xml2js": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.5.tgz", + "integrity": "sha512-yohU3zMn0fkhlape1nxXG2bLEGZRc1FeqF80RoHaYXJN7uibaauXfhzhOJr1Xh36sn+/tx21QAOf07b/xYVk1w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { - "version": "15.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", - "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==", + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.5.tgz", + "integrity": "sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -519,11 +562,94 @@ "dev": true }, "@types/zen-observable": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.0.tgz", - "integrity": "sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.1.tgz", + "integrity": "sha512-wmk0xQI6Yy7Fs/il4EpOcflG4uonUpYGqvZARESLc2oy4u69fkatFLbJOeW4Q6awO15P4rduAe6xkwHevpXcUQ==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.1.1.tgz", + "integrity": "sha512-Hoxyt99EA9LMmqo/5PuWWPeWeB3mKyvibfJ1Hy5SfiUpjE8Nqp+5QNd9fOkzL66+fqvIWSIE+Ett16LGMzCGnQ==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.1.1", + "@typescript-eslint/scope-manager": "4.1.1", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.1.1.tgz", + "integrity": "sha512-jzYsNciHoa4Z3c1URtmeT/bamYm8Dwfw6vuN3WHIE/BXb1iC4KveAnXDErTAZtPVxTYBaYn3n2gbt6F6D2rm1A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.1.1", + "@typescript-eslint/types": "4.1.1", + "@typescript-eslint/typescript-estree": "4.1.1", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.1.1.tgz", + "integrity": "sha512-NLIhmicpKGfJbdXyQBz9j48PA6hq6e+SDOoXy7Ak6bq1ebGqbgG+fR1UIDAuay6OjQdot69c/URu2uLlsP8GQQ==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.1.1", + "@typescript-eslint/types": "4.1.1", + "@typescript-eslint/typescript-estree": "4.1.1", + "debug": "^4.1.1" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.1.1.tgz", + "integrity": "sha512-0W8TTobCvIIQ2FsrYTffyZGAAFUyIbEHq5EYJb1m7Rpd005jrnOvKOo8ywCLhs/Bm17C+KsrUboBvBAARQVvyA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.1.1", + "@typescript-eslint/visitor-keys": "4.1.1" + } + }, + "@typescript-eslint/types": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.1.1.tgz", + "integrity": "sha512-zrBiqOKYerMTllKcn+BP+i1b7LW/EbMMYytroXMxUTvFPn1smkCu0D7lSAx29fTUO4jnwV0ljSvYQtn2vNrNxA==", "dev": true }, + "@typescript-eslint/typescript-estree": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.1.1.tgz", + "integrity": "sha512-2AUg5v0liVBsqbGxBphbJ0QbGqSRVaF5qPoTPWcxop+66vMdU1h4CCvHxTC47+Qb+Pr4l2RhXDd41JNpwcQEKw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.1.1", + "@typescript-eslint/visitor-keys": "4.1.1", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.1.1.tgz", + "integrity": "sha512-/EOOXbA2ferGLG6RmCHEQ0lTTLkOlXYDgblCmQk3tIU7mTPLm4gKhFMeeUSe+bcchTUsKeCk8xcpbop5Zr/8Rw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.1.1", + "eslint-visitor-keys": "^2.0.0" + } + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -541,9 +667,15 @@ "dev": true }, "acorn": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", - "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", "dev": true }, "adal-node": { @@ -564,9 +696,9 @@ }, "dependencies": { "@types/node": { - "version": "8.10.59", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.59.tgz", - "integrity": "sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ==", + "version": "8.10.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.63.tgz", + "integrity": "sha512-g+nSkeHFDd2WOQChfmy9SAXLywT47WZBrGS/NC5ym5PJ8c8RC6l4pbGaUW/X0+eZJnXw6/AVNEouXWhV4iz72Q==", "dev": true } } @@ -578,27 +710,19 @@ "dev": true }, "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==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" - }, - "dependencies": { - "indent-string": { - "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 - } } }, "ajv": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", - "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -615,13 +739,10 @@ "optional": true }, "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true }, "ansi-cyan": { "version": "0.1.1", @@ -633,10 +754,21 @@ } }, "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==", - "dev": true + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "dev": true, + "requires": { + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } + } }, "ansi-gray": { "version": "0.1.1", @@ -682,12 +814,6 @@ "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", "dev": true }, - "any-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", - "dev": true - }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -796,6 +922,15 @@ "to-regex": "^3.0.2" } }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", @@ -842,38 +977,6 @@ "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "arg": { @@ -1016,6 +1119,39 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", + "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.4" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -1049,6 +1185,12 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -1101,9 +1243,9 @@ "dev": true }, "aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", "dev": true }, "axios": { @@ -1206,6 +1348,17 @@ "tweetnacl": "^0.14.3" } }, + "better-sqlite3": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-7.1.1.tgz", + "integrity": "sha512-AkvGGyhAVZhRBOul2WT+5CB2EuveM3ZkebEKe1wxMqDZUy1XB/1RBgM66t0ybHC4DIni8+pr7NaLqEX87NUTwg==", + "dev": true, + "requires": { + "bindings": "^1.5.0", + "prebuild-install": "^5.3.3", + "tar": "4.4.10" + } + }, "bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", @@ -1219,9 +1372,9 @@ "dev": true }, "binaryextensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.2.0.tgz", - "integrity": "sha512-bHhs98rj/7i/RZpCSJ3uk55pLXOItjIrh2sRQZSM6OoktScX+LxJzvlU+FELp9j3TdcddTmmYArLSGptCTwjuw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", + "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", "dev": true }, "bindings": { @@ -1229,63 +1382,44 @@ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, - "optional": true, "requires": { "file-uri-to-path": "1.0.0" } }, "bl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", - "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", + "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", "dev": true, "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" }, "dependencies": { "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } } } }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "optional": true, + "requires": { + "inherits": "~2.0.0" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1311,15 +1445,15 @@ "dev": true }, "bson": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.3.tgz", - "integrity": "sha512-TdiJxMVnodVS7r0BdL42y/pqC9cL2iKynVwA0Ho3qbsQYr428veL3l7BQyuqiw+Q5SqqoT0m4srSY/BlZ9AxXg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", + "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==", "dev": true }, "buffer": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.5.0.tgz", - "integrity": "sha512-9FTEDjLjwoAkEwyMGDjYJQN2gfRgOKBKRfiglhvibGbpeeU/pQn1bJxQqm32OD/AIeEuHxU9roxXxg34Byp/Ww==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" @@ -1349,12 +1483,6 @@ "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", "dev": true }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -1384,22 +1512,14 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - } + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" } }, "cardinal": { @@ -1442,14 +1562,20 @@ } }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -1554,12 +1680,6 @@ "is-buffer": "^1.1.5" } }, - "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 - }, "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", @@ -1585,9 +1705,9 @@ "dev": true }, "class-transformer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.2.3.tgz", - "integrity": "sha512-qsP+0xoavpOlJHuYsQJsN58HXSl8Jvveo+T37rEvCEeRfMWoytAyR0Ua/YsFgpM6AZYZ/og2PJwArwzJl1aXtQ==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.3.1.tgz", + "integrity": "sha512-cKFwohpJbuMovS8xVLmn8N2AUbAuc8pVo4zEfsUVo8qgECOogns1WVk/FkOZoxhOPTyTYFckuoH+13FO+MQ8GA==", "dev": true }, "class-utils": { @@ -1620,12 +1740,12 @@ "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=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "requires": { - "restore-cursor": "^2.0.0" + "restore-cursor": "^3.1.0" } }, "cli-highlight": { @@ -1639,55 +1759,72 @@ "parse5": "^5.1.1", "parse5-htmlparser2-tree-adapter": "^5.1.1", "yargs": "^15.0.0" - } - }, - "cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", - "dev": true, - "requires": { - "slice-ansi": "0.0.4", - "string-width": "^1.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 - }, - "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, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "requires": { - "number-is-nan": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^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": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" } + } + } + }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" } } } }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -1725,38 +1862,6 @@ "inherits": "^2.0.1", "process-nextick-args": "^2.0.0", "readable-stream": "^2.3.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "code-point-at": { @@ -1815,19 +1920,19 @@ } }, "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz", + "integrity": "sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==", "dev": true }, "compare-func": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz", - "integrity": "sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, "requires": { "array-ify": "^1.0.0", - "dot-prop": "^3.0.0" + "dot-prop": "^5.1.0" } }, "compare-versions": { @@ -1857,38 +1962,6 @@ "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "console-control-strings": { @@ -1898,172 +1971,181 @@ "dev": true }, "conventional-changelog": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.18.tgz", - "integrity": "sha512-aN6a3rjgV8qwAJj3sC/Lme2kvswWO7fFSGQc32gREcwIOsaiqBaO6f2p0NomFaPDnTqZ+mMZFLL3hlzvEnZ0mQ==", + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.23.tgz", + "integrity": "sha512-sScUu2NHusjRC1dPc5p8/b3kT78OYr95/Bx7Vl8CPB8tF2mG1xei5iylDTRjONV5hTlzt+Cn/tBWrKdd299b7A==", "dev": true, "requires": { - "conventional-changelog-angular": "^5.0.6", - "conventional-changelog-atom": "^2.0.3", - "conventional-changelog-codemirror": "^2.0.3", - "conventional-changelog-conventionalcommits": "^4.2.3", - "conventional-changelog-core": "^4.1.4", - "conventional-changelog-ember": "^2.0.4", - "conventional-changelog-eslint": "^3.0.4", - "conventional-changelog-express": "^2.0.1", - "conventional-changelog-jquery": "^3.0.6", - "conventional-changelog-jshint": "^2.0.3", - "conventional-changelog-preset-loader": "^2.3.0" + "conventional-changelog-angular": "^5.0.11", + "conventional-changelog-atom": "^2.0.7", + "conventional-changelog-codemirror": "^2.0.7", + "conventional-changelog-conventionalcommits": "^4.4.0", + "conventional-changelog-core": "^4.2.0", + "conventional-changelog-ember": "^2.0.8", + "conventional-changelog-eslint": "^3.0.8", + "conventional-changelog-express": "^2.0.5", + "conventional-changelog-jquery": "^3.0.10", + "conventional-changelog-jshint": "^2.0.8", + "conventional-changelog-preset-loader": "^2.3.4" } }, "conventional-changelog-angular": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz", - "integrity": "sha512-QDEmLa+7qdhVIv8sFZfVxU1VSyVvnXPsxq8Vam49mKUcO1Z8VTLEJk9uI21uiJUsnmm0I4Hrsdc9TgkOQo9WSA==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.11.tgz", + "integrity": "sha512-nSLypht/1yEflhuTogC03i7DX7sOrXGsRn14g131Potqi6cbGbGEE9PSDEHKldabB6N76HiSyw9Ph+kLmC04Qw==", "dev": true, "requires": { - "compare-func": "^1.3.1", + "compare-func": "^2.0.0", "q": "^1.5.1" } }, "conventional-changelog-atom": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.3.tgz", - "integrity": "sha512-szZe2ut97qNO6vCCMkm1I/tWu6ol4Rr8a9Lx0y/VlpDnpY0PNp+oGpFgU55lplhx+I3Lro9Iv4/gRj0knfgjzg==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.7.tgz", + "integrity": "sha512-7dOREZwzB+tCEMjRTDfen0OHwd7vPUdmU0llTy1eloZgtOP4iSLVzYIQqfmdRZEty+3w5Jz+AbhfTJKoKw1JeQ==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-cli": { - "version": "2.0.31", - "resolved": "https://registry.npmjs.org/conventional-changelog-cli/-/conventional-changelog-cli-2.0.31.tgz", - "integrity": "sha512-nMINylKAamBLM3OmD7/44d9TPZ3V58IDTXoGC/QtXxve+1Sj37BQTzIEW3TNaviZ2ZV/b5Dqg0eSk4DNP5fBdA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-cli/-/conventional-changelog-cli-2.1.0.tgz", + "integrity": "sha512-hZ8EcpxV4LcGOZwH+U5LJQDnyA4o/uyUdmIGzmFZMB4caujavvDBo/iTgVihk0m1QKkEhJgulagrILSm1JCakA==", "dev": true, "requires": { "add-stream": "^1.0.0", - "conventional-changelog": "^3.1.18", + "conventional-changelog": "^3.1.23", "lodash": "^4.17.15", - "meow": "^5.0.0", + "meow": "^7.0.0", "tempfile": "^3.0.0" } }, "conventional-changelog-codemirror": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.3.tgz", - "integrity": "sha512-t2afackdgFV2yBdHhWPqrKbpaQeVnz2hSJKdWqjasPo5EpIB6TBL0er3cOP1mnGQmuzk9JSvimNSuqjWGDtU5Q==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.7.tgz", + "integrity": "sha512-Oralk1kiagn3Gb5cR5BffenWjVu59t/viE6UMD/mQa1hISMPkMYhJIqX+CMeA1zXgVBO+YHQhhokEj99GP5xcg==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-conventionalcommits": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.2.3.tgz", - "integrity": "sha512-atGa+R4vvEhb8N/8v3IoW59gCBJeeFiX6uIbPu876ENAmkMwsenyn0R21kdDHJFLQdy6zW4J6b4xN8KI3b9oww==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.4.0.tgz", + "integrity": "sha512-ybvx76jTh08tpaYrYn/yd0uJNLt5yMrb1BphDe4WBredMlvPisvMghfpnJb6RmRNcqXeuhR6LfGZGewbkRm9yA==", "dev": true, "requires": { - "compare-func": "^1.3.1", + "compare-func": "^2.0.0", "lodash": "^4.17.15", "q": "^1.5.1" } }, "conventional-changelog-core": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.1.4.tgz", - "integrity": "sha512-LO58ZbEpp1Ul+y/vOI8rJRsWkovsYkCFbOCVgi6UnVfU8WC0F8K8VQQwaBZWWUpb6JvEiN4GBR5baRP2txZ+Vg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.0.tgz", + "integrity": "sha512-8+xMvN6JvdDtPbGBqA7oRNyZD4od1h/SIzrWqHcKZjitbVXrFpozEeyn4iI4af1UwdrabQpiZMaV07fPUTGd4w==", "dev": true, "requires": { "add-stream": "^1.0.0", - "conventional-changelog-writer": "^4.0.11", - "conventional-commits-parser": "^3.0.8", + "conventional-changelog-writer": "^4.0.17", + "conventional-commits-parser": "^3.1.0", "dateformat": "^3.0.0", "get-pkg-repo": "^1.0.0", "git-raw-commits": "2.0.0", "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^3.0.1", + "git-semver-tags": "^4.1.0", "lodash": "^4.17.15", "normalize-package-data": "^2.3.5", "q": "^1.5.1", "read-pkg": "^3.0.0", "read-pkg-up": "^3.0.0", + "shelljs": "^0.8.3", "through2": "^3.0.0" } }, "conventional-changelog-ember": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.4.tgz", - "integrity": "sha512-q1u73sO9uCnxN4TSw8xu6MRU8Y1h9kpwtcdJuNRwu/LSKI1IE/iuNSH5eQ6aLlQ3HTyrIpTfUuVybW4W0F17rA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.8.tgz", + "integrity": "sha512-JEMEcUAMg4Q9yxD341OgWlESQ4gLqMWMXIWWUqoQU8yvTJlKnrvcui3wk9JvnZQyONwM2g1MKRZuAjKxr8hAXA==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-eslint": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.4.tgz", - "integrity": "sha512-CPwTUENzhLGl3auunrJxiIEWncAGaby7gOFCdj2gslIuOFJ0KPJVOUhRz4Da/I53sdo/7UncUJkiLg94jEsjxg==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.8.tgz", + "integrity": "sha512-5rTRltgWG7TpU1PqgKHMA/2ivjhrB+E+S7OCTvj0zM/QGg4vmnVH67Vq/EzvSNYtejhWC+OwzvDrLk3tqPry8A==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-express": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.1.tgz", - "integrity": "sha512-G6uCuCaQhLxdb4eEfAIHpcfcJ2+ao3hJkbLrw/jSK/eROeNfnxCJasaWdDAfFkxsbpzvQT4W01iSynU3OoPLIw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.5.tgz", + "integrity": "sha512-pW2hsjKG+xNx/Qjof8wYlAX/P61hT5gQ/2rZ2NsTpG+PgV7Rc8RCfITvC/zN9K8fj0QmV6dWmUefCteD9baEAw==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-jquery": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.6.tgz", - "integrity": "sha512-gHAABCXUNA/HjnZEm+vxAfFPJkgtrZvCDIlCKfdPVXtCIo/Q0lN5VKpx8aR5p8KdVRQFF3OuTlvv5kv6iPuRqA==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.10.tgz", + "integrity": "sha512-QCW6wF8QgPkq2ruPaxc83jZxoWQxLkt/pNxIDn/oYjMiVgrtqNdd7lWe3vsl0hw5ENHNf/ejXuzDHk6suKsRpg==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-jshint": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.3.tgz", - "integrity": "sha512-Pc2PnMPcez634ckzr4EOWviwRSpZcURaK7bjyD9oK6N5fsC/a+3G7LW5m/JpcHPhA9ZxsfIbm7uqZ3ZDGsQ/sw==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.8.tgz", + "integrity": "sha512-hB/iI0IiZwnZ+seYI+qEQ4b+EMQSEC8jGIvhO2Vpz1E5p8FgLz75OX8oB1xJWl+s4xBMB6f8zJr0tC/BL7YOjw==", "dev": true, "requires": { - "compare-func": "^1.3.1", + "compare-func": "^2.0.0", "q": "^1.5.1" } }, "conventional-changelog-preset-loader": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.0.tgz", - "integrity": "sha512-/rHb32J2EJnEXeK4NpDgMaAVTFZS3o1ExmjKMtYVgIC4MQn0vkNSbYpdGRotkfGGRWiqk3Ri3FBkiZGbAfIfOQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", + "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", "dev": true }, "conventional-changelog-writer": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.11.tgz", - "integrity": "sha512-g81GQOR392I+57Cw3IyP1f+f42ME6aEkbR+L7v1FBBWolB0xkjKTeCWVguzRrp6UiT1O6gBpJbEy2eq7AnV1rw==", + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.17.tgz", + "integrity": "sha512-IKQuK3bib/n032KWaSb8YlBFds+aLmzENtnKtxJy3+HqDq5kohu3g/UdNbIHeJWygfnEbZjnCKFxAW0y7ArZAw==", "dev": true, "requires": { - "compare-func": "^1.3.1", - "conventional-commits-filter": "^2.0.2", + "compare-func": "^2.0.0", + "conventional-commits-filter": "^2.0.6", "dateformat": "^3.0.0", - "handlebars": "^4.4.0", + "handlebars": "^4.7.6", "json-stringify-safe": "^5.0.1", "lodash": "^4.17.15", - "meow": "^5.0.0", + "meow": "^7.0.0", "semver": "^6.0.0", "split": "^1.0.0", "through2": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "conventional-commits-filter": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz", - "integrity": "sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.6.tgz", + "integrity": "sha512-4g+sw8+KA50/Qwzfr0hL5k5NWxqtrOVw4DDk3/h6L85a9Gz0/Eqp3oP+CWCNfesBvZZZEFHF7OTEbRe+yYSyKw==", "dev": true, "requires": { "lodash.ismatch": "^4.4.0", @@ -2071,15 +2153,15 @@ } }, "conventional-commits-parser": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.0.8.tgz", - "integrity": "sha512-YcBSGkZbYp7d+Cr3NWUeXbPDFUN6g3SaSIzOybi8bjHL5IJ5225OSCxJJ4LgziyEJ7AaJtE9L2/EU6H7Nt/DDQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.1.0.tgz", + "integrity": "sha512-RSo5S0WIwXZiRxUGTPuYFbqvrR4vpJ1BDdTlthFgvHt5kEdnd1+pdvwWphWn57/oIl4V72NMmOocFqqJ8mFFhA==", "dev": true, "requires": { "JSONStream": "^1.0.4", "is-text-path": "^1.0.1", "lodash": "^4.17.15", - "meow": "^5.0.0", + "meow": "^7.0.0", "split2": "^2.0.0", "through2": "^3.0.0", "trim-off-newlines": "^1.0.0" @@ -2125,58 +2207,27 @@ "dev": true }, "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", + "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "dependencies": { - "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-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - } + "yaml": "^1.10.0" } }, "cross-spawn": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", - "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.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" - } - } } }, "css": { @@ -2229,19 +2280,14 @@ } }, "data-api-client": { - "version": "github:ArsenyYankovsky/data-api-client#42a4a26b5d7de0939b748d6d22a67022a9955a6f", - "from": "github:ArsenyYankovsky/data-api-client#support-date", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-api-client/-/data-api-client-1.1.0.tgz", + "integrity": "sha512-ZO6i4g55afRYbDwpVuF3pa6KI0pNee5VcAGAIQRHhCFAJytFCwazzSQ3iwZU8ONcRumXoHDKTp/dyIQOub1ysg==", "dev": true, "requires": { "sqlstring": "^2.3.1" } }, - "date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", - "dev": true - }, "date-utils": { "version": "1.2.21", "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", @@ -2313,6 +2359,15 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dev": true, + "requires": { + "mimic-response": "^2.0.0" + } + }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -2427,6 +2482,24 @@ "p-map": "^3.0.0", "rimraf": "^3.0.0", "slash": "^3.0.0" + }, + "dependencies": { + "globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + } } }, "delayed-stream": { @@ -2484,23 +2557,24 @@ "dev": true, "requires": { "path-type": "^4.0.0" - }, - "dependencies": { - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - } } }, - "dot-prop": { + "doctrine": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", - "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "requires": { - "is-obj": "^1.0.0" + "is-obj": "^2.0.0" } }, "dotenv": { @@ -2518,38 +2592,6 @@ "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "each-props": { @@ -2587,12 +2629,6 @@ "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", "dev": true }, - "elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", - "dev": true - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2607,6 +2643,15 @@ "once": "^1.4.0" } }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2617,22 +2662,71 @@ } }, "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "version": "1.18.0-next.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", + "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", "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.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", + "is-callable": "^1.2.0", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "es-get-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", + "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", + "dev": true, + "requires": { + "es-abstract": "^1.17.4", + "has-symbols": "^1.0.1", + "is-arguments": "^1.0.4", + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } } }, "es-to-primitive": { @@ -2690,6 +2784,11 @@ "es6-symbol": "^3.1.1" } }, + "escalade": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", + "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -2714,6 +2813,42 @@ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", "dev": true }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "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" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, "source-map": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", @@ -2723,45 +2858,205 @@ "requires": { "amdefine": ">=0.0.4" } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } } } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "execa": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz", - "integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==", + "eslint": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.9.0.tgz", + "integrity": "sha512-V6QyhX21+uXp4T+3nrNfI3hQNBDa/P8ga7LoQOenwrlEFXrEnUEE+ok1dMtaS3b6rmLXhT1TkTIsG75HMLbknA==", "dev": true, "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "is-stream": "^2.0.0", + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.1.3", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.3.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "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 + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, + "espree": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "execa": { + "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": "^7.0.0", + "get-stream": "^5.0.0", + "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^3.0.0", "onetime": "^5.1.0", @@ -2820,6 +3115,12 @@ } } }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true + }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -2839,9 +3140,9 @@ }, "dependencies": { "type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", - "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", "dev": true } } @@ -2873,6 +3174,17 @@ } } }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -2957,15 +3269,15 @@ } }, "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "fast-glob": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz", - "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -2989,35 +3301,42 @@ "dev": true }, "fastq": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.1.tgz", - "integrity": "sha512-mpIH5sKYueh3YyeJwqtVo8sORi0CgtmkVbK6kZStpQlZBYQuTzG2CZ7idSiJuA7bY0SFCWUc5WIs+oYumGCQNw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", + "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", "dev": true, "requires": { "reusify": "^1.0.4" } }, "figlet": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.3.0.tgz", - "integrity": "sha512-f7A8aOJAfyehLJ7lQ6rEA8WJw7kOk3lfWRi5piSjkzbK5YkI5sqO8eiLHz1ehO+DM0QYB85i8VfA6XIGUbU1dg==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.5.0.tgz", + "integrity": "sha512-ZQJM4aifMpz6H19AW1VqvZ7l4pOE9p7i/3LyxgO2kp+PO/VcDYNqIHEMtkccqIhTXMKci4kjueJr/iCQEaT/Ww==" }, "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "flat-cache": "^2.0.1" } }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true + "dev": true }, "fill-range": { "version": "7.0.1", @@ -3199,48 +3518,44 @@ } } }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "glob": "^7.1.3" } } } }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, "follow-redirects": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", @@ -3308,6 +3623,12 @@ "map-cache": "^0.2.2" } }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, "fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", @@ -3327,36 +3648,6 @@ "through2": "^2.0.3" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -3375,615 +3666,109 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", - "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, "optional": true, "requires": { "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" + "nan": "^2.12.1" + } + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" }, "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, - "optional": true + "optional": true, + "requires": { + "minimist": "^1.2.5" + } }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "optional": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "glob": "^7.1.3" } + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "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 }, - "balanced-match": { + "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, - "optional": true + "requires": { + "number-is-nan": "^1.0.0" + } }, - "brace-expansion": { - "version": "1.1.11", - "bundled": 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, - "optional": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, - "chownr": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "bundled": true, - "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 - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "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 - }, - "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, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "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=", + "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" @@ -4065,19 +3850,6 @@ "repeating": "^2.0.0" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", @@ -4102,21 +3874,6 @@ "trim-newlines": "^1.0.0" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", @@ -4137,12 +3894,6 @@ "pinkie-promise": "^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": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -4164,21 +3915,6 @@ "read-pkg": "^1.0.0" } }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", @@ -4189,30 +3925,6 @@ "strip-indent": "^1.0.1" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", @@ -4247,24 +3959,12 @@ "dev": true }, "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { "pump": "^3.0.0" - }, - "dependencies": { - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } } }, "get-value": { @@ -4295,6 +3995,35 @@ "through2": "^2.0.0" }, "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.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 + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, "meow": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", @@ -4312,42 +4041,38 @@ "trim-newlines": "^2.0.0" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" } }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -4357,6 +4082,12 @@ "readable-stream": "~2.3.6", "xtend": "~4.0.1" } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true } } }, @@ -4368,24 +4099,24 @@ "requires": { "gitconfiglocal": "^1.0.0", "pify": "^2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } } }, "git-semver-tags": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-3.0.1.tgz", - "integrity": "sha512-Hzd1MOHXouITfCasrpVJbRDg9uvW7LfABk3GQmXYZByerBDrfrEMP9HXpNT7RxAbieiocP6u+xq20DkvjwxnCA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.0.tgz", + "integrity": "sha512-TcxAGeo03HdErzKzi4fDD+xEL7gi8r2Y5YSxH6N2XYdVSV5UkBwfrt7Gqo1b+uSHCjy/sa9Y6BBBxxFLxfbhTg==", "dev": true, "requires": { - "meow": "^5.0.0", + "meow": "^7.0.0", "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "gitconfiglocal": { @@ -4397,6 +4128,12 @@ "ini": "^1.3.2" } }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "dev": true + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -4411,9 +4148,9 @@ } }, "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -4455,43 +4192,13 @@ "requires": { "is-extglob": "^2.1.0" } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } } } }, "glob-watcher": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", - "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -4499,6 +4206,7 @@ "chokidar": "^2.0.0", "is-negated-glob": "^1.0.0", "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", "object.defaults": "^1.1.0" } }, @@ -4524,21 +4232,47 @@ "ini": "^1.3.4", "is-windows": "^1.0.1", "which": "^1.2.14" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + }, + "dependencies": { + "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 + } } }, "globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", "dev": true, "requires": { - "@types/glob": "^7.1.1", "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", "slash": "^3.0.0" } }, @@ -4552,9 +4286,9 @@ } }, "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==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, "growl": { @@ -4575,6 +4309,15 @@ "vinyl-fs": "^3.0.0" }, "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -4615,9 +4358,9 @@ "dev": true }, "gulp-cli": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", - "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", "dev": true, "requires": { "ansi-colors": "^1.0.1", @@ -4628,7 +4371,7 @@ "copy-props": "^2.0.1", "fancy-log": "^1.3.2", "gulplog": "^1.0.0", - "interpret": "^1.1.0", + "interpret": "^1.4.0", "isobject": "^3.0.1", "liftoff": "^3.1.0", "matchdep": "^2.0.0", @@ -4636,7 +4379,7 @@ "pretty-hrtime": "^1.0.0", "replace-homedir": "^1.0.0", "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.0.1", + "v8flags": "^3.2.0", "yargs": "^7.1.0" } }, @@ -4649,28 +4392,6 @@ "number-is-nan": "^1.0.0" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", @@ -4691,12 +4412,6 @@ "pinkie-promise": "^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": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -4735,74 +4450,338 @@ "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=", + "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" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "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, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", + "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "5.0.0-security.0" + } + }, + "yargs-parser": { + "version": "5.0.0-security.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", + "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + } + }, + "gulp-eslint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-6.0.0.tgz", + "integrity": "sha512-dCVPSh1sA+UVhn7JSQt7KEb4An2sQNbOdB3PA8UCfxsoPlAKjJHxYHGXdXC7eb+V1FAnilSFFqslPrq037l1ig==", + "dev": true, + "requires": { + "eslint": "^6.0.0", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "eslint": { + "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", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.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": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-utils": { + "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.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "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 + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "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" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "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": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "shebang-regex": "^1.0.0" } }, - "which-module": { + "shebang-regex": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-regex": "^4.1.0" } }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" + "has-flag": "^3.0.0" } }, - "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "camelcase": "^3.0.0" + "isexe": "^2.0.0" } } } @@ -4821,34 +4800,54 @@ "vinyl-sourcemaps-apply": "^0.2.1" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" } }, "through2": { @@ -4980,6 +4979,16 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -4990,10 +4999,19 @@ "path-exists": "^3.0.0" } }, + "mkdirp": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, "mocha": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.2.tgz", - "integrity": "sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", + "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -5008,7 +5026,7 @@ "js-yaml": "3.13.1", "log-symbols": "2.2.0", "minimatch": "3.0.4", - "mkdirp": "0.5.1", + "mkdirp": "0.5.4", "ms": "2.1.1", "node-environment-flags": "1.0.5", "object.assign": "4.1.0", @@ -5016,8 +5034,8 @@ "supports-color": "6.0.0", "which": "1.3.1", "wide-align": "1.1.3", - "yargs": "13.3.0", - "yargs-parser": "13.1.1", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", "yargs-unparser": "1.6.0" }, "dependencies": { @@ -5038,6 +5056,18 @@ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "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" + } + }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -5053,29 +5083,6 @@ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "dependencies": { - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - } - } - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -5096,6 +5103,15 @@ "ansi-regex": "^4.1.0" } }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, "wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", @@ -5108,9 +5124,9 @@ } }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { "cliui": "^5.0.0", @@ -5122,13 +5138,13 @@ "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^13.1.2" } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -5152,38 +5168,6 @@ "istextorbinary": "2.2.1", "readable-stream": "^2.0.1", "replacestream": "^4.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "gulp-shell": { @@ -5200,16 +5184,14 @@ "tslib": "^1.10.0" }, "dependencies": { - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } } } @@ -5233,36 +5215,12 @@ "through2": "2.X" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -5275,77 +5233,20 @@ } } }, - "gulp-tslint": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/gulp-tslint/-/gulp-tslint-8.1.4.tgz", - "integrity": "sha512-wBoZIEMJRz9urHwolsvQpngA9l931p6g/Liwz1b/KrsVP6jEBFZv/o0NS1TFCQZi/l8mXxz8+v3twhf4HOXxPQ==", - "dev": true, - "requires": { - "@types/fancy-log": "1.3.0", - "ansi-colors": "^1.0.1", - "fancy-log": "1.3.3", - "map-stream": "~0.0.7", - "plugin-error": "1.0.1", - "through": "~2.3.8" - }, - "dependencies": { - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - } - } - } - }, "gulp-typescript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-5.0.1.tgz", - "integrity": "sha512-YuMMlylyJtUSHG1/wuSVTrZp60k1dMEFKYOvDf7OvbAJWrDtxxD4oZon4ancdWwzjj30ztiidhe4VXJniF0pIQ==", + "version": "6.0.0-alpha.1", + "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-6.0.0-alpha.1.tgz", + "integrity": "sha512-KoT0TTfjfT7w3JItHkgFH1T/zK4oXWC+a8xxKfniRfVcA0Fa1bKrIhztYelYmb+95RB80OLMBreknYkdwzdi2Q==", "dev": true, "requires": { - "ansi-colors": "^3.0.5", + "ansi-colors": "^4.1.1", "plugin-error": "^1.0.1", "source-map": "^0.7.3", - "through2": "^3.0.0", - "vinyl": "^2.1.0", + "through2": "^3.0.1", + "vinyl": "^2.2.0", "vinyl-fs": "^3.0.3" }, "dependencies": { - "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", - "dev": true - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "dependencies": { - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - } - } - }, "source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", @@ -5377,15 +5278,16 @@ } }, "handlebars": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.3.tgz", - "integrity": "sha512-SRGwSYuNfx8DwHD/6InAPzD6RgeruWLT+B8e8a7gGs8FWgHzlExpTFMEq2IA6QpAfOClpKHy6+8IqTjeBCu6Kg==", + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", "dev": true, "requires": { + "minimist": "^1.2.5", "neo-async": "^2.6.0", - "optimist": "^0.6.1", "source-map": "^0.6.1", - "uglify-js": "^3.1.4" + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" } }, "har-schema": { @@ -5395,15 +5297,21 @@ "dev": true }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -5504,9 +5412,9 @@ "dev": true }, "highlight.js": { - "version": "9.18.1", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz", - "integrity": "sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg==" + "version": "9.18.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.3.tgz", + "integrity": "sha512-zBZAmhSupHIl5sITeMqIJnYCDfAEc3Gdkqj65wC1lpI468MMQeeQkhcIAvk+RylAkxrCcI9xy9piHiXeQ1BdzQ==" }, "homedir-polyfill": { "version": "1.0.3", @@ -5541,15 +5449,15 @@ "dev": true }, "husky": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.3.tgz", - "integrity": "sha512-VxTsSTRwYveKXN4SaH1/FefRJYCtx+wx04sSVcOpD7N2zjoHxa+cEJ07Qg5NmV3HAK+IRKOyNVpi2YBIVccIfQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", + "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", "dev": true, "requires": { - "chalk": "^3.0.0", + "chalk": "^4.0.0", "ci-info": "^2.0.0", - "compare-versions": "^3.5.1", - "cosmiconfig": "^6.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^7.0.0", "find-versions": "^3.2.0", "opencollective-postinstall": "^2.0.2", "pkg-dir": "^4.2.0", @@ -5559,9 +5467,9 @@ } }, "iconv-lite": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz", - "integrity": "sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" @@ -5573,9 +5481,9 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true }, "ignore-walk": { @@ -5597,10 +5505,16 @@ "resolve-from": "^4.0.0" } }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "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": { @@ -5623,10 +5537,31 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + } + }, "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true }, "invert-kv": { @@ -5665,6 +5600,12 @@ } } }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5687,9 +5628,9 @@ "dev": true }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz", + "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==", "dev": true }, "is-data-descriptor": { @@ -5769,12 +5710,24 @@ "is-extglob": "^2.1.1" } }, + "is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", + "dev": true + }, "is-negated-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", "dev": true }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5782,20 +5735,11 @@ "dev": true }, "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true }, - "is-observable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", - "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", - "dev": true, - "requires": { - "symbol-observable": "^1.1.0" - } - }, "is-path-cwd": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", @@ -5824,9 +5768,9 @@ } }, "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", "dev": true }, "is-property": { @@ -5836,12 +5780,12 @@ "dev": true }, "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { - "has": "^1.0.3" + "has-symbols": "^1.0.1" } }, "is-regexp": { @@ -5859,12 +5803,24 @@ "is-unc-path": "^1.0.0" } }, + "is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", + "dev": true + }, "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 }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", @@ -5987,6 +5943,15 @@ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", @@ -6002,11 +5967,14 @@ "has-flag": "^1.0.0" } }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -6031,6 +5999,22 @@ "textextensions": "2" } }, + "iterate-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", + "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==", + "dev": true + }, + "iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dev": true, + "requires": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6038,18 +6022,18 @@ "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, "jsbi": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.1.2.tgz", - "integrity": "sha512-5nDXo1X9QVaXK/Cpb5VECV9ss1QPbjUuk1qSruHB1PK/g39Sd414K4nci99ElFDZv0vzxDEnKn3o49/Tn9Yagw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.1.4.tgz", + "integrity": "sha512-52QRRFSsi9impURE8ZUbzAMCLjPm4THO7H2fcuIvaaeFTbSysvkodbQQXIVsNgq/ypDbq6dJiuGKL0vZ/i9hUg==", "dev": true }, "jsbn": { @@ -6064,6 +6048,12 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -6113,9 +6103,9 @@ "dev": true }, "just-extend": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", - "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", + "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", "dev": true }, "jwa": { @@ -6162,38 +6152,6 @@ "dev": true, "requires": { "readable-stream": "^2.0.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "lcid": { @@ -6215,13 +6173,13 @@ } }, "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, "liftoff": { @@ -6247,19 +6205,21 @@ "dev": true }, "lint-staged": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.0.8.tgz", - "integrity": "sha512-Oa9eS4DJqvQMVdywXfEor6F4vP+21fPHF8LUXgBbVWUSWBddjqsvO6Bv1LwMChmgQZZqwUvgJSHlu8HFHAPZmA==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.3.0.tgz", + "integrity": "sha512-an3VgjHqmJk0TORB/sdQl0CTkRg4E5ybYCXTTCSJ5h9jFwZbcgKIx5oVma5e7wp/uKt17s1QYFmYqT9MGVosGw==", "dev": true, "requires": { - "chalk": "^3.0.0", - "commander": "^4.0.1", - "cosmiconfig": "^6.0.0", + "chalk": "^4.1.0", + "cli-truncate": "^2.1.0", + "commander": "^6.0.0", + "cosmiconfig": "^7.0.0", "debug": "^4.1.1", "dedent": "^0.7.0", - "execa": "^3.4.0", - "listr": "^0.14.3", - "log-symbols": "^3.0.0", + "enquirer": "^2.3.6", + "execa": "^4.0.3", + "listr2": "^2.6.0", + "log-symbols": "^4.0.0", "micromatch": "^4.0.2", "normalize-path": "^3.0.0", "please-upgrade-node": "^3.2.0", @@ -6267,40 +6227,10 @@ "stringify-object": "^3.3.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, "execa": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", - "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", + "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -6310,45 +6240,19 @@ "merge-stream": "^2.0.0", "npm-run-path": "^4.0.0", "onetime": "^5.1.0", - "p-finally": "^2.0.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "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==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", "dev": true, "requires": { - "chalk": "^2.4.2" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - } + "chalk": "^4.0.0" } }, - "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-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -6357,207 +6261,60 @@ "requires": { "path-key": "^3.0.0" } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, - "listr": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", - "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "listr2": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-2.6.2.tgz", + "integrity": "sha512-6x6pKEMs8DSIpA/tixiYY2m/GcbgMplMVmhQAaLFxEtNSKLeWTGjtmU57xvv6QCm2XcqzyNXL/cTSVf4IChCRA==", "dev": true, "requires": { - "@samverschueren/stream-to-observable": "^0.3.0", - "is-observable": "^1.1.0", - "is-promise": "^2.1.0", - "is-stream": "^1.1.0", - "listr-silent-renderer": "^1.1.1", - "listr-update-renderer": "^0.5.0", - "listr-verbose-renderer": "^0.5.0", - "p-map": "^2.0.0", - "rxjs": "^6.3.3" + "chalk": "^4.1.0", + "cli-truncate": "^2.1.0", + "figures": "^3.2.0", + "indent-string": "^4.0.0", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rxjs": "^6.6.2", + "through": "^2.3.8" }, "dependencies": { - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, "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": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", - "dev": true - }, - "listr-update-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", - "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^2.3.0", - "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 - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, - "requires": { - "chalk": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "aggregate-error": "^3.0.0" } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true } } }, - "listr-verbose-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", - "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "chalk": "^2.4.1", - "cli-cursor": "^2.1.0", - "date-fns": "^1.27.2", - "figures": "^2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "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" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "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": { - "has-flag": "^3.0.0" + "error-ex": "^1.2.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" - } - }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -6567,9 +6324,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, "lodash._reinterpolate": { @@ -6671,55 +6428,32 @@ } }, "log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { + "astral-regex": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" } } } @@ -6780,15 +6514,9 @@ "dev": true }, "map-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", - "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", + "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", "dev": true }, "map-visit": { @@ -6962,35 +6690,61 @@ "optional": true }, "meow": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", - "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", - "dev": true, - "requires": { - "camelcase-keys": "^4.0.0", - "decamelize-keys": "^1.0.0", - "loud-rejection": "^1.0.0", - "minimist-options": "^3.0.1", - "normalize-package-data": "^2.3.4", - "read-pkg-up": "^3.0.0", - "redent": "^2.0.0", - "trim-newlines": "^2.0.0", - "yargs-parser": "^10.0.0" + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.1.tgz", + "integrity": "sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^2.5.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.13.1", + "yargs-parser": "^18.1.3" }, "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true + "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" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "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 + } } } } @@ -7002,9 +6756,9 @@ "dev": true }, "merge2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", - "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, "micromatch": { @@ -7018,18 +6772,18 @@ } }, "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", "dev": true }, "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", "dev": true, "requires": { - "mime-db": "1.43.0" + "mime-db": "1.44.0" } }, "mimic-fn": { @@ -7038,6 +6792,18 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -7047,18 +6813,20 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true }, "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "requires": { "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" } }, "minipass": { @@ -7102,51 +6870,49 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true }, "mocha": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.0.tgz", - "integrity": "sha512-MymHK8UkU0K15Q/zX7uflZgVoRWiTjy0fXE/QjKts6mowUvGxOdPhZ2qj3b0iZdUrNZlW9LAIMFHB4IW+2b3EQ==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.3.tgz", + "integrity": "sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw==", "dev": true, "requires": { - "ansi-colors": "3.2.3", + "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.3.0", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", + "chokidar": "3.4.2", + "debug": "4.1.1", + "diff": "4.0.2", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", + "js-yaml": "3.14.0", + "log-symbols": "4.0.0", "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "ms": "2.1.1", - "node-environment-flags": "1.0.6", + "ms": "2.1.2", "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", + "promise.allsettled": "1.0.2", + "serialize-javascript": "4.0.0", + "strip-json-comments": "3.0.1", + "supports-color": "7.1.0", + "which": "2.0.2", "wide-align": "1.1.3", - "yargs": "13.3.0", - "yargs-parser": "13.1.1", - "yargs-unparser": "1.6.0" + "workerpool": "6.0.0", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.1" }, "dependencies": { - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", @@ -7173,47 +6939,25 @@ } }, "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==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", "dev": true, "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.1.1", + "fsevents": "~2.1.2", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" + "readdirp": "~3.4.0" } }, "cliui": { @@ -7242,14 +6986,11 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true }, "emoji-regex": { "version": "7.0.3", @@ -7257,42 +6998,29 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" } }, "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "dev": true, "optional": true }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -7309,76 +7037,62 @@ "dev": true }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" } }, "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==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", "dev": true, "requires": { - "chalk": "^2.4.2" + "chalk": "^4.0.0" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node-environment-flags": { - "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==", + "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": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" } }, - "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 + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } }, "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "p-limit": "^3.0.2" } }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, "readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", "dev": true, "requires": { - "picomatch": "^2.0.4" + "picomatch": "^2.2.1" } }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -7399,13 +7113,19 @@ "ansi-regex": "^4.1.0" } }, + "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==", + "dev": true + }, "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "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": "^3.0.0" + "has-flag": "^4.0.0" } }, "wrap-ansi": { @@ -7420,9 +7140,9 @@ } }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { "cliui": "^5.0.0", @@ -7434,18 +7154,150 @@ "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "yargs-unparser": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", + "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "decamelize": "^1.2.0", + "flat": "^4.1.0", + "is-plain-obj": "^1.1.0", + "yargs": "^14.2.3" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "yargs": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" + } + }, + "yargs-parser": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", + "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } } } }, @@ -7456,17 +7308,29 @@ "dev": true }, "mongodb": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.5.tgz", - "integrity": "sha512-GCjDxR3UOltDq00Zcpzql6dQo1sVry60OXJY3TDmFc2SWFY6c8Gn1Ardidc5jDirvJrx2GC3knGOImKphbSL3A==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.2.tgz", + "integrity": "sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA==", "dev": true, "requires": { - "bl": "^2.2.0", - "bson": "^1.1.1", + "bl": "^2.2.1", + "bson": "^1.1.4", "denque": "^1.4.1", "require_optional": "^1.0.1", "safe-buffer": "^5.1.2", "saslprep": "^1.0.0" + }, + "dependencies": { + "bl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + } } }, "ms": { @@ -7475,9 +7339,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "mssql": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/mssql/-/mssql-6.1.0.tgz", - "integrity": "sha512-tlzqjnWkV2Ra5TuPh/Snmp1CF/+yDJOPjQ2yoVzdvl0vQePPFITSLQCBLRydNbg8sR6HXQFEIQL9mPaCA3oO0Q==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/mssql/-/mssql-6.2.1.tgz", + "integrity": "sha512-erINJ9EUPvPuWXifZfhum0CVEVrdvnFYlpgU6WKkQW69W4W7DWqJS2FHdedHnuJWlJ8x1WW1NcD8GFfF15O2aA==", "dev": true, "requires": { "debug": "^4", @@ -7491,6 +7355,12 @@ "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", "dev": true }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, "mysql": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", @@ -7503,35 +7373,11 @@ "sqlstring": "2.3.1" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } } } }, @@ -7550,6 +7396,17 @@ "named-placeholders": "^1.1.2", "seq-queue": "^0.0.5", "sqlstring": "^2.3.1" + }, + "dependencies": { + "iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "mz": { @@ -7590,10 +7447,11 @@ } }, "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true, + "optional": true }, "nanomatch": { "version": "1.2.13", @@ -7614,16 +7472,28 @@ "to-regex": "^3.0.1" } }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, "native-duplexpair": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/native-duplexpair/-/native-duplexpair-1.0.0.tgz", "integrity": "sha1-eJkHjmS/PIo9cyYBs9QP8F21j6A=", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "needle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.3.tgz", - "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", + "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", "dev": true, "requires": { "debug": "^3.2.6", @@ -7639,22 +7509,13 @@ "requires": { "ms": "^2.1.1" } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } } } }, "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, "next-tick": { @@ -7663,10 +7524,16 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "nise": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.3.tgz", - "integrity": "sha512-EGlhjm7/4KvmmE6B/UFsKh7eHykRl9VH+au8dduHLCyWUO/hr7+N+WtTvDUwc9zHuM1IaIJs/0lQ6Ag1jDkQSg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", + "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0", @@ -7676,6 +7543,29 @@ "path-to-regexp": "^1.7.0" } }, + "node-abi": { + "version": "2.19.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.1.tgz", + "integrity": "sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A==", + "dev": true, + "requires": { + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "node-addon-api": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz", + "integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA==", + "dev": true + }, "node-environment-flags": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", @@ -7694,6 +7584,78 @@ } } }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "dev": true, + "optional": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "dev": true, + "optional": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "optional": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "node-pre-gyp": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", @@ -7712,6 +7674,15 @@ "tar": "^4" }, "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, "nopt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", @@ -7739,6 +7710,12 @@ } } }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", + "dev": true + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -7769,13 +7746,10 @@ } }, "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true }, "now-and-later": { "version": "2.0.1", @@ -7882,9 +7856,9 @@ } }, "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==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", "dev": true }, "object-keys": { @@ -7903,15 +7877,15 @@ } }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, "object.defaults": { @@ -7934,6 +7908,27 @@ "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "object.map": { @@ -7974,44 +7969,40 @@ } }, "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "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==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", "dev": true }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "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" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" } }, + "oracledb": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/oracledb/-/oracledb-5.0.0.tgz", + "integrity": "sha512-NLE3t6KiAkpBHA1/zgjNiKaa9Z4Nnp4PuB3d0b3Kz4C8klrIrMKfHIGUySlwqgDW588m7/2hnPxU7PH6wjBd6g==", + "dev": true + }, "ordered-read-streams": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", @@ -8019,38 +8010,6 @@ "dev": true, "requires": { "readable-stream": "^2.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "os-homedir": { @@ -8091,9 +8050,9 @@ "dev": true }, "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { "p-try": "^2.0.0" } @@ -8158,13 +8117,15 @@ "dev": true }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", "dev": true, "requires": { + "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" } }, "parse-node-version": { @@ -8259,13 +8220,10 @@ } }, "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" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true }, "pathval": { "version": "1.1.0", @@ -8280,16 +8238,16 @@ "dev": true }, "pg": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.18.2.tgz", - "integrity": "sha512-Mvt0dGYMwvEADNKy5PMQGlzPudKcKKzJds/VbOeZJpb6f/pI3mmoXX0JksPgI3l3JPP/2Apq7F36O63J7mgveA==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.3.3.tgz", + "integrity": "sha512-wmUyoQM/Xzmo62wgOdQAn5tl7u+IA1ZYK7qbuppi+3E+Gj4hlUxVHjInulieWrd0SfHi/ADriTb5ILJ/lsJrSg==", "dev": true, "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.10", + "pg-connection-string": "^2.3.0", + "pg-pool": "^3.2.1", + "pg-protocol": "^1.2.5", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" @@ -8304,9 +8262,9 @@ } }, "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=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.3.0.tgz", + "integrity": "sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w==", "dev": true }, "pg-int8": { @@ -8315,16 +8273,16 @@ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", "dev": true }, - "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": "3.2.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.1.tgz", + "integrity": "sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA==", "dev": true }, - "pg-pool": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.10.tgz", - "integrity": "sha512-qdwzY92bHf3nwzIUcj+zJ0Qo5lpG/YxchahxIN8+ZVmXqkahKXsnl2aiJPHLYN9o5mB/leG+Xh6XKxtP7e0sjg==", + "pg-protocol": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.5.tgz", + "integrity": "sha512-1uYCckkuTfzz/FCefvavRywkowa6M5FohNMF5OjKrqo9PSR8gYc8poVmwwYQaBxhmQdBjhtP514eXy9/Us2xKg==", "dev": true }, "pg-types": { @@ -8350,15 +8308,15 @@ } }, "picomatch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", - "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "pinkie": { @@ -8395,54 +8353,25 @@ } }, "plugin-error": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", - "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", "dev": true, "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" }, "dependencies": { - "arr-diff": { + "ansi-colors": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", - "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" - } - }, - "arr-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", - "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", - "dev": true - }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, - "extend-shallow": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", - "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "dev": true, "requires": { - "kind-of": "^1.1.0" + "ansi-wrap": "^0.1.0" } - }, - "kind-of": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", - "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", - "dev": true } } }, @@ -8465,9 +8394,9 @@ "dev": true }, "postgres-date": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.4.tgz", - "integrity": "sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", "dev": true }, "postgres-interval": { @@ -8479,10 +8408,44 @@ "xtend": "^4.0.0" } }, + "prebuild-install": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.5.tgz", + "integrity": "sha512-YmMO7dph9CYKi5IR/BzjOJlRzpxGGVo1EsLSUZ0mt/Mq0HWZIHOKHHcHdT69yG54C9m6i45GpItwRHpk0Py7Uw==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp": "^0.5.1", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, "pretty-hrtime": { @@ -8497,6 +8460,46 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise.allsettled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", + "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", + "dev": true, + "requires": { + "array.prototype.map": "^1.0.1", + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "iterate-value": "^1.0.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -8504,15 +8507,15 @@ "dev": true }, "psl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", - "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -8528,6 +8531,18 @@ "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } } }, "punycode": { @@ -8549,11 +8564,20 @@ "dev": true }, "quick-lru": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", - "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -8564,14 +8588,6 @@ "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - } } }, "read-pkg": { @@ -8583,6 +8599,51 @@ "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", "path-type": "^3.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "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" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } } }, "read-pkg-up": { @@ -8647,14 +8708,26 @@ } }, "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } } }, "readdirp": { @@ -8761,36 +8834,6 @@ "to-regex": "^3.0.2" } }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", @@ -8813,13 +8856,13 @@ } }, "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" } }, "redeyed": { @@ -8844,9 +8887,9 @@ } }, "redis-commands": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", - "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.6.0.tgz", + "integrity": "sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ==", "dev": true }, "redis-errors": { @@ -8869,12 +8912,6 @@ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, - "regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", - "dev": true - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -8885,6 +8922,12 @@ "safe-regex": "^1.1.0" } }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, "remap-istanbul": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/remap-istanbul/-/remap-istanbul-0.13.0.tgz", @@ -8898,18 +8941,6 @@ "through2": "3.0.0" }, "dependencies": { - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - } - }, "through2": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.0.tgz", @@ -8943,46 +8974,6 @@ "through2": "^2.0.3" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -9023,9 +9014,9 @@ } }, "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", "dev": true }, "replace-homedir": { @@ -9048,38 +9039,6 @@ "escape-string-regexp": "^1.0.3", "object-assign": "^4.0.1", "readable-stream": "^2.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "request": { @@ -9158,9 +9117,9 @@ } }, "resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -9198,30 +9157,13 @@ "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=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "requires": { - "onetime": "^2.0.0", + "onetime": "^5.1.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" - } - } } }, "ret": { @@ -9245,6 +9187,12 @@ "glob": "^7.1.3" } }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, "run-parallel": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", @@ -9252,18 +9200,18 @@ "dev": true }, "rxjs": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", - "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safe-regex": { "version": "1.1.0", @@ -9296,9 +9244,9 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true }, "semver-compare": { @@ -9328,6 +9276,15 @@ "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=", "dev": true }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -9380,24 +9337,52 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shelljs": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "dev": true }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "dev": true, + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "sinon": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.1.tgz", - "integrity": "sha512-iTTyiQo5T94jrOx7X7QLBZyucUJ2WvL9J13+96HMfm2CGoJYbIPqRfl6wgNcqmzk0DI28jeGx5bUTXizkrqBmg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.3.tgz", + "integrity": "sha512-IKo9MIM111+smz9JGwLmw5U1075n1YXeAq8YeSFlndCLhAL5KGn6bLgu7b/4AYHTV/LcEMcRm2wU2YiL55/6Pg==", "dev": true, "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/commons": "^1.7.2", + "@sinonjs/fake-timers": "^6.0.1", "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.0.3", + "@sinonjs/samsam": "^5.1.0", "diff": "^4.0.2", - "nise": "^4.0.1", + "nise": "^4.0.4", "supports-color": "^7.1.0" }, "dependencies": { @@ -9422,10 +9407,47 @@ "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" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } }, "snapdragon": { "version": "0.8.2", @@ -9575,9 +9597,9 @@ } }, "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -9607,9 +9629,9 @@ } }, "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -9617,15 +9639,15 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -9665,36 +9687,6 @@ "through2": "^2.0.2" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -9713,20 +9705,20 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sql.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.0.0.tgz", - "integrity": "sha512-fl/cQu8hDbu9bXNXTrmwwtS2wvHttWrXS9fzINVtedOBOJJWMjwSADR1aQ+DKmCdGNF4jrg/15AedJ5kcrWRJA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.3.0.tgz", + "integrity": "sha512-bxrJ/9rqJ2SA6hpHnSodRjKBugZHewRvNTITTt74W1VZWmzODjdS68yQW0/J9oC0NWKylHEtV1ptkoTyOYO4Tw==", "dev": true }, "sqlite3": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz", - "integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.0.tgz", + "integrity": "sha512-rjvqHFUaSGnzxDy2AHCwhHy6Zp6MNJzCPGYju4kD8yi6bze4d1/zMTg6C7JI49b7/EM7jKMTvyfN/4ylBKdwfw==", "dev": true, "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.11.0", - "request": "^2.87.0" + "node-addon-api": "2.0.0", + "node-gyp": "3.x", + "node-pre-gyp": "^0.11.0" } }, "sqlstring": { @@ -9807,33 +9799,83 @@ "strip-ansi": "^6.0.0" } }, - "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, - "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } } }, "stringify-object": { @@ -9845,6 +9887,14 @@ "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + } } }, "strip-ansi": { @@ -9856,10 +9906,13 @@ } }, "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } }, "strip-bom-string": { "version": "1.0.0", @@ -9874,10 +9927,13 @@ "dev": true }, "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } }, "strip-json-comments": { "version": "2.0.1", @@ -9886,9 +9942,9 @@ "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==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { "has-flag": "^4.0.0" } @@ -9903,25 +9959,120 @@ "es6-symbol": "^3.1.1" } }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true - }, + "table": { + "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", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", + "integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==", "dev": true, "requires": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", + "minipass": "^2.3.5", "minizlib": "^1.2.1", "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", "yallist": "^3.0.3" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "tar-fs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", + "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, + "tar-stream": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", + "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "tarn": { @@ -9950,20 +10101,40 @@ }, "dependencies": { "@types/node": { - "version": "12.12.29", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.29.tgz", - "integrity": "sha512-yo8Qz0ygADGFptISDj3pOC9wXfln/5pQaN/ysDIzOaAWXt73cNHmtEC8zSO2Y+kse/txmwIAJzkYZ5fooaS5DQ==", + "version": "12.12.58", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.58.tgz", + "integrity": "sha512-Be46CNIHWAagEfINOjmriSxuv7IVcqbGe+sDSg2SYCEz/0CRBy7LRASGfRbD8KZkqoePU73Wsx3UvOSFcq/9hA==", "dev": true }, "bl": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz", - "integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.1.tgz", + "integrity": "sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ==", "dev": true, "requires": { "readable-stream": "^3.0.1" } }, + "iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "sprintf-js": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", @@ -9994,6 +10165,12 @@ "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "textextensions": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.6.0.tgz", @@ -10001,9 +10178,9 @@ "dev": true }, "thenify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", - "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "requires": { "any-promise": "^1.0.0" } @@ -10023,11 +10200,12 @@ "dev": true }, "through2": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", - "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", "dev": true, "requires": { + "inherits": "^2.0.4", "readable-stream": "2 || 3" } }, @@ -10041,36 +10219,6 @@ "xtend": "~4.0.0" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -10099,6 +10247,15 @@ "next-tick": "1" } }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "to-absolute-glob": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", @@ -10159,36 +10316,6 @@ "through2": "^2.0.3" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -10212,9 +10339,9 @@ } }, "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", + "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", "dev": true }, "trim-off-newlines": { @@ -10224,15 +10351,15 @@ "dev": true }, "ts-node": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.6.2.tgz", - "integrity": "sha512-4mZEbofxGqLL2RImpe3zMJukvEvcO1XP8bj8ozBPySdCUXEcU5cIRwR0aM3R+VoZq7iXc8N86NC0FspGRqP4gg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", + "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", "dev": true, "requires": { "arg": "^4.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.6", + "source-map-support": "^0.5.17", "yn": "3.1.1" }, "dependencies": { @@ -10245,99 +10372,14 @@ } }, "tslib": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==" - }, - "tslint": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.0.tgz", - "integrity": "sha512-fXjYd/61vU6da04E505OZQGb2VCN2Mq3doeWcOIryuG+eqdmFUXTYVwdhnbEu2k46LNLgUYt9bI5icQze/j0bQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.10.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" }, "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", "dev": true, "requires": { "tslib": "^1.8.1" @@ -10371,12 +10413,12 @@ "dev": true }, "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "^1.2.1" } }, "type-detect": { @@ -10385,6 +10427,12 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -10392,30 +10440,26 @@ "dev": true }, "typeorm-aurora-data-api-driver": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/typeorm-aurora-data-api-driver/-/typeorm-aurora-data-api-driver-1.1.8.tgz", - "integrity": "sha512-rN3wJWkZfLmb9G/JZ5XfxtI4o7nKZVi8/3+husvxsU7valkkBYn+IXXJcyXuRfDU09nJqbxrcvc0aNZGYSiInA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/typeorm-aurora-data-api-driver/-/typeorm-aurora-data-api-driver-1.4.0.tgz", + "integrity": "sha512-uGoVZvuStFknrhQuSzpdhdm7TG3XcOWrkHH47oMY8qNcNrYGEGkiK5Msqpoqu9nfEEY+HG6sDSx0ssmfmkF31g==", "dev": true, "requires": { - "data-api-client": "github:ArsenyYankovsky/data-api-client#support-date" + "data-api-client": "^1.1.0" } }, "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", "dev": true }, "uglify-js": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.8.0.tgz", - "integrity": "sha512-ugNSTT8ierCsDHso2jkBHXYrU8Y5/fY2ZUprfrJUiD7YpuFvV4jODLFmb3h4btQjqr5Nh4TX4XtgDfCU1WdioQ==", + "version": "3.10.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.4.tgz", + "integrity": "sha512-kBFT3U4Dcj4/pJ52vfjCSfyLyvG9VYYuGYPmrPvAxRw/i7xHiT4VvCev+uiEMcEEiu6UNB6KgWmGtSUYIWScbw==", "dev": true, - "optional": true, - "requires": { - "commander": "~2.20.3", - "source-map": "~0.6.1" - } + "optional": true }, "unc-path-regex": { "version": "0.1.2", @@ -10424,15 +10468,15 @@ "dev": true }, "underscore": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz", - "integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz", + "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw==", "dev": true }, "undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", "dev": true, "requires": { "arr-flatten": "^1.0.1", @@ -10440,10 +10484,19 @@ "bach": "^1.0.0", "collection-map": "^1.0.0", "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", "last-run": "^1.1.0", "object.defaults": "^1.0.0", "object.reduce": "^1.0.0", "undertaker-registry": "^1.0.0" + }, + "dependencies": { + "fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", + "dev": true + } } }, "undertaker-registry": { @@ -10521,9 +10574,9 @@ "dev": true }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -10553,10 +10606,16 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, "v8flags": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", "dev": true, "requires": { "homedir-polyfill": "^1.0.1" @@ -10628,36 +10687,6 @@ "vinyl-sourcemap": "^1.1.0" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -10683,6 +10712,17 @@ "now-and-later": "^2.0.0", "remove-bom-buffer": "^3.0.0", "vinyl": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, "vinyl-sourcemaps-apply": { @@ -10703,9 +10743,9 @@ } }, "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "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" @@ -10771,9 +10811,15 @@ "dev": true }, "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "workerpool": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", + "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", "dev": true }, "wrap-ansi": { @@ -10791,6 +10837,26 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, "xml2js": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", @@ -10835,13 +10901,10 @@ "dev": true }, "yaml": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.8.2.tgz", - "integrity": "sha512-omakb0d7FjMo3R1D2EbTKVIk6dAVLRxFXdLZMEUToeAvuqgG/YuHMuQOZ5fgk+vQ8cx+cnGKwyg+8g8PNT0xQg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.7" - } + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "dev": true }, "yargonaut": { "version": "1.1.4", @@ -10891,27 +10954,55 @@ } }, "yargs": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.0.tgz", - "integrity": "sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA==", - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.0.3.tgz", + "integrity": "sha512-6+nLw8xa9uK1BOEOykaiYAJVh6/CjxWXK/q9b5FpRgNslt8s22F2xMBqVIKgCRjNgGvGPBy8Vog7WN7yh4amtA==", + "requires": { + "cliui": "^7.0.0", + "escalade": "^3.0.2", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.0" + "y18n": "^5.0.1", + "yargs-parser": "^20.0.0" + }, + "dependencies": { + "cliui": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.1.tgz", + "integrity": "sha512-rcvHOWyGyid6I1WjT/3NatKj2kDt9OdSHSXpyLXaMWFbKpGACNW8pRhhdPUq9MWUOdwn8Rz9AVETjF4105rZZQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.1.tgz", + "integrity": "sha512-/jJ831jEs4vGDbYPQp4yGKDYPSCCEQ45uZWJHE1AoYBzqdZi8+LDWas0z4HrmJXmKdpFsTiowSHXdxyFhpmdMg==" + }, + "yargs-parser": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.0.0.tgz", + "integrity": "sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA==" + } } }, "yargs-parser": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.0.tgz", - "integrity": "sha512-o/Jr6JBOv6Yx3pL+5naWSoIA2jJ+ZkMYQG/ie9qFbukBe4uzmBatlXFOiu/tNKRWEtyf+n5w7jc/O16ufqOTdQ==", + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -11047,9 +11138,9 @@ } }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { "cliui": "^5.0.0", @@ -11061,13 +11152,13 @@ "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^13.1.2" } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { "camelcase": "^5.0.0", diff --git a/package.json b/package.json index ab91051806..194b93ddc3 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ }, "main": "./index.js", "browser": { + "./browser/driver/aurora-data-api/AuroraDataApiDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", + "./browser/driver/cockroachdb/CockroachDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/postgres/PostgresDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/oracle/OracleDriver.ts": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/driver/sap/SapDriver.ts": "./browser/platform/BrowserDisabledDriversDummy.js", @@ -20,6 +22,9 @@ "./browser/driver/mongodb/MongoQueryRunner.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/entity-manager/MongoEntityManager.js": "./browser/platform/BrowserDisabledDriversDummy.js", "./browser/repository/MongoRepository.js": "./browser/platform/BrowserDisabledDriversDummy.js", + "./browser/driver/sqlite/SqliteDriver.js": "./browser/platform/BrowserDisabledDriversDummy.js", + "./browser/driver/better-sqlite3/BetterSqlite3Driver.js": "./browser/platform/BrowserDisabledDriversDummy.js", + "./browser/util/DirectoryExportedClassesLoader.js": "./browser/platform/BrowserDirectoryExportedClassesLoader.js", "./index.js": "./browser/index.js" }, "repository": { @@ -47,86 +52,96 @@ "oracle-orm" ], "devDependencies": { - "@types/chai": "^4.2.10", - "@types/chai-as-promised": "^7.1.2", + "@types/app-root-path": "^1.2.4", + "@types/chai": "^4.2.0", + "@types/chai-as-promised": "^7.1.3", "@types/debug": "^4.1.5", - "@types/mocha": "^7.0.2", - "@types/node": "^13.9.0", - "@types/rimraf": "^2.0.3", + "@types/dotenv": "^8.2.0", + "@types/js-yaml": "^3.12.5", + "@types/mkdirp": "^1.0.1", + "@types/mocha": "^8.0.3", + "@types/node": "^14.6.4", + "@types/rimraf": "^3.0.0", "@types/sha.js": "^2.4.0", - "@types/sinon": "^7.5.2", + "@types/sinon": "^9.0.5", "@types/source-map-support": "^0.5.1", + "@types/xml2js": "^0.4.5", "@types/yargs": "^15.0.4", "@types/zen-observable": "^0.8.0", + "@typescript-eslint/eslint-plugin": "^4.1.0", + "@typescript-eslint/parser": "^4.1.0", + "better-sqlite3": "^7.1.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "class-transformer": "^0.2.3", - "conventional-changelog-angular": "^5.0.3", - "conventional-changelog-cli": "^2.0.21", + "class-transformer": "^0.3.1", + "conventional-changelog-angular": "^5.0.11", + "conventional-changelog-cli": "^2.1.0", "del": "^5.1.0", + "eslint": "^7.8.1", "gulp": "^4.0.2", + "gulp-eslint": "^6.0.0", "gulp-istanbul": "^1.1.3", "gulp-mocha": "^7.0.2", "gulp-rename": "^2.0.0", "gulp-replace": "^1.0.0", "gulp-shell": "^0.8.0", "gulp-sourcemaps": "^2.6.5", - "gulp-tslint": "^8.1.4", - "gulp-typescript": "^5.0.0", + "gulp-typescript": "^6.0.0-alpha.1", "gulpclass": "^0.2.0", "husky": "^4.2.3", "lint-staged": "^10.0.8", - "mocha": "^7.1.0", + "mocha": "^8.1.3", "mongodb": "^3.5.4", "mssql": "^6.1.0", "mysql": "^2.18.1", "mysql2": "^2.1.0", - "pg": "^7.18.2", + "oracledb": "^5.0.0", + "pg": "^8.3.0", "redis": "^3.0.2", "remap-istanbul": "^0.13.0", "rimraf": "^3.0.2", "sinon": "^9.0.0", "sinon-chai": "^3.5.0", "source-map-support": "^0.5.16", - "sql.js": "^1.0.0", - "sqlite3": "^4.0.9", - "ts-node": "^8.6.2", - "tslint": "^6.0.0", - "typeorm-aurora-data-api-driver": "^1.1.1", - "typescript": "^3.8.3" + "sql.js": "^1.3.0", + "sqlite3": "^5.0.0", + "ts-node": "^9.0.0", + "typeorm-aurora-data-api-driver": "^1.4.0", + "typescript": "^3.9.7" }, "dependencies": { + "@sqltools/formatter": "1.2.2", "app-root-path": "^3.0.0", "buffer": "^5.5.0", - "chalk": "^3.0.0", + "chalk": "^4.1.0", "cli-highlight": "^2.1.4", "debug": "^4.1.1", "dotenv": "^8.2.0", "glob": "^7.1.6", - "js-yaml": "^3.13.1", - "mkdirp": "^0.5.1", + "js-yaml": "^3.14.0", + "mkdirp": "^1.0.4", "reflect-metadata": "^0.1.13", "sha.js": "^2.4.11", - "tslib": "^1.11.1", + "tslib": "^1.13.0", "xml2js": "^0.4.23", "yargonaut": "^1.1.2", - "yargs": "^15.3.0", + "yargs": "^16.0.3", "zen-observable": "^0.8.15" }, "lint-staged": { "*.ts": [ - "tslint --fix", + "eslint --fix", "git add" ] }, "scripts": { - "watch": "./node_modules/.bin/tsc -w", "test-ci": "gulp ci-tests", "test": "rimraf ./build && tsc && mocha --file ./build/compiled/test/utils/test-setup.js --bail --recursive --timeout 60000 ./build/compiled/test", "test-fast": "mocha --file ./build/compiled/test/utils/test-setup.js --bail --recursive --timeout 60000 ./build/compiled/test", "compile": "rimraf ./build && tsc", + "watch": "./node_modules/.bin/tsc -w", "package": "gulp package", - "lint": "tslint -p .", + "lint": "eslint -c ./.eslintrc.js src/**/*.ts test/**/*.ts sample/**/*.ts", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 2" }, "bin": { diff --git a/sample/sample24-schemas/schemas/image.json b/sample/sample24-schemas/schemas/image.json index c16eb5efb0..cfbb911df1 100644 --- a/sample/sample24-schemas/schemas/image.json +++ b/sample/sample24-schemas/schemas/image.json @@ -25,7 +25,7 @@ "cascade": true, "inverseSide": "images" }, - "secondaryImages": { + "secondaryPost": { "target": "Post", "type": "many-to-one", "cascade": true, diff --git a/src/cache/DbQueryResultCache.ts b/src/cache/DbQueryResultCache.ts index 34dc8e4442..be243ce6ac 100644 --- a/src/cache/DbQueryResultCache.ts +++ b/src/cache/DbQueryResultCache.ts @@ -229,7 +229,7 @@ export class DbQueryResultCache implements QueryResultCache { if (queryRunner) return queryRunner; - return this.connection.createQueryRunner("master"); + return this.connection.createQueryRunner(); } } diff --git a/src/cache/RedisQueryResultCache.ts b/src/cache/RedisQueryResultCache.ts index 735a427980..afda734a26 100644 --- a/src/cache/RedisQueryResultCache.ts +++ b/src/cache/RedisQueryResultCache.ts @@ -185,8 +185,11 @@ export class RedisQueryResultCache implements QueryResultCache { */ protected loadRedis(): any { try { - return PlatformTools.load(this.clientType); - + if (this.clientType === "ioredis/cluster") { + return PlatformTools.load("ioredis"); + } else { + return PlatformTools.load(this.clientType); + } } catch (e) { throw new Error(`Cannot use cache because ${this.clientType} is not installed. Please run "npm i ${this.clientType} --save".`); } diff --git a/src/commands/CacheClearCommand.ts b/src/commands/CacheClearCommand.ts index 76c48f17a6..79dba0e87a 100644 --- a/src/commands/CacheClearCommand.ts +++ b/src/commands/CacheClearCommand.ts @@ -2,8 +2,7 @@ import {createConnection} from "../index"; import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import {Connection} from "../connection/Connection"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Clear cache command. diff --git a/src/commands/CommandUtils.ts b/src/commands/CommandUtils.ts index 7aaecae7c8..bd42c4ba5c 100644 --- a/src/commands/CommandUtils.ts +++ b/src/commands/CommandUtils.ts @@ -1,7 +1,6 @@ import * as fs from "fs"; import * as path from "path"; - -const mkdirp = require("mkdirp"); +import mkdirp from "mkdirp"; /** * Command line utils functions. @@ -12,7 +11,7 @@ export class CommandUtils { * Creates directories recursively. */ static createDirectories(directory: string) { - return new Promise((ok, fail) => mkdirp(directory, (err: any) => err ? fail(err) : ok())); + return mkdirp(directory); } /** diff --git a/src/commands/EntityCreateCommand.ts b/src/commands/EntityCreateCommand.ts index a79487bec0..314fa203d1 100644 --- a/src/commands/EntityCreateCommand.ts +++ b/src/commands/EntityCreateCommand.ts @@ -1,8 +1,7 @@ import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import {CommandUtils} from "./CommandUtils"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Generates a new entity. diff --git a/src/commands/InitCommand.ts b/src/commands/InitCommand.ts index 902a2874a5..3dbe7f2c51 100644 --- a/src/commands/InitCommand.ts +++ b/src/commands/InitCommand.ts @@ -2,8 +2,7 @@ import {CommandUtils} from "./CommandUtils"; import {ObjectLiteral} from "../common/ObjectLiteral"; import * as path from "path"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Generates a new project with TypeORM. @@ -114,6 +113,12 @@ export class InitCommand implements yargs.CommandModule { "database": "database.sqlite", }); break; + case "better-sqlite3": + Object.assign(options, { + type: "better-sqlite3", + "database": "database.sqlite", + }); + break; case "postgres": Object.assign(options, { "type": "postgres", @@ -458,6 +463,7 @@ services: `; case "sqlite": + case "better-sqlite3": return `version: '3' services: `; @@ -547,6 +553,9 @@ Steps to run this project: case "sqlite": packageJson.dependencies["sqlite3"] = "^4.0.3"; break; + case "better-sqlite3": + packageJson.dependencies["better-sqlite3"] = "^7.0.0"; + break; case "oracle": packageJson.dependencies["oracledb"] = "^1.13.1"; break; diff --git a/src/commands/MigrationCreateCommand.ts b/src/commands/MigrationCreateCommand.ts index 6a1396880c..a39247e919 100644 --- a/src/commands/MigrationCreateCommand.ts +++ b/src/commands/MigrationCreateCommand.ts @@ -2,8 +2,7 @@ import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import {CommandUtils} from "./CommandUtils"; import {camelCase} from "../util/StringUtils"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Creates a new migration file. @@ -46,7 +45,7 @@ export class MigrationCreateCommand implements yargs.CommandModule { const timestamp = new Date().getTime(); const fileContent = MigrationCreateCommand.getTemplate(args.name as any, timestamp); const filename = timestamp + "-" + args.name + ".ts"; - let directory = args.dir; + let directory = args.dir as string; // if directory is not set then try to open tsconfig and find default path there if (!directory) { @@ -56,11 +55,11 @@ export class MigrationCreateCommand implements yargs.CommandModule { configName: args.config as any }); const connectionOptions = await connectionOptionsReader.get(args.connection as any); - directory = connectionOptions.cli ? connectionOptions.cli.migrationsDir : undefined; + directory = connectionOptions.cli ? (connectionOptions.cli.migrationsDir || "") : ""; } catch (err) { } } - const path = process.cwd() + "/" + (directory ? (directory + "/") : "") + filename; + const path = (directory.startsWith("/") ? "" : process.cwd() + "/") + (directory ? (directory + "/") : "") + filename; await CommandUtils.createFile(path, fileContent); console.log(`Migration ${chalk.blue(path)} has been generated successfully.`); diff --git a/src/commands/MigrationGenerateCommand.ts b/src/commands/MigrationGenerateCommand.ts index 7aec78ffd9..a17005ca2d 100644 --- a/src/commands/MigrationGenerateCommand.ts +++ b/src/commands/MigrationGenerateCommand.ts @@ -6,8 +6,8 @@ import {MysqlDriver} from "../driver/mysql/MysqlDriver"; import {camelCase} from "../util/StringUtils"; import * as yargs from "yargs"; import {AuroraDataApiDriver} from "../driver/aurora-data-api/AuroraDataApiDriver"; - -const chalk = require("chalk"); +import chalk from "chalk"; +import { format } from "@sqltools/formatter/lib/sqlFormatter"; /** * Generates a new migration file with sql needs to be executed to update schema. @@ -34,6 +34,12 @@ export class MigrationGenerateCommand implements yargs.CommandModule { alias: "dir", describe: "Directory where migration should be created." }) + .option("p", { + alias: "pretty", + type: "boolean", + default: false, + describe: "Pretty-print generated SQL", + }) .option("f", { alias: "config", default: "ormconfig", @@ -77,23 +83,33 @@ export class MigrationGenerateCommand implements yargs.CommandModule { }); connection = await createConnection(connectionOptions); const sqlInMemory = await connection.driver.createSchemaBuilder().log(); + + if (args.pretty) { + sqlInMemory.upQueries.forEach(upQuery => { + upQuery.query = MigrationGenerateCommand.prettifyQuery(upQuery.query); + }); + sqlInMemory.downQueries.forEach(downQuery => { + downQuery.query = MigrationGenerateCommand.prettifyQuery(downQuery.query); + }); + } + const upSqls: string[] = [], downSqls: string[] = []; // mysql is exceptional here because it uses ` character in to escape names in queries, that's why for mysql // we are using simple quoted string instead of template string syntax if (connection.driver instanceof MysqlDriver || connection.driver instanceof AuroraDataApiDriver) { sqlInMemory.upQueries.forEach(upQuery => { - upSqls.push(" await queryRunner.query(\"" + upQuery.query.replace(new RegExp(`"`, "g"), `\\"`) + "\", " + JSON.stringify(upQuery.parameters) + ");"); + upSqls.push(" await queryRunner.query(\"" + upQuery.query.replace(new RegExp(`"`, "g"), `\\"`) + "\"" + MigrationGenerateCommand.queryParams(upQuery.parameters) + ");"); }); sqlInMemory.downQueries.forEach(downQuery => { - downSqls.push(" await queryRunner.query(\"" + downQuery.query.replace(new RegExp(`"`, "g"), `\\"`) + "\", " + JSON.stringify(downQuery.parameters) + ");"); + downSqls.push(" await queryRunner.query(\"" + downQuery.query.replace(new RegExp(`"`, "g"), `\\"`) + "\"" + MigrationGenerateCommand.queryParams(downQuery.parameters) + ");"); }); } else { sqlInMemory.upQueries.forEach(upQuery => { - upSqls.push(" await queryRunner.query(`" + upQuery.query.replace(new RegExp("`", "g"), "\\`") + "`, " + JSON.stringify(upQuery.parameters) + ");"); + upSqls.push(" await queryRunner.query(`" + upQuery.query.replace(new RegExp("`", "g"), "\\`") + "`" + MigrationGenerateCommand.queryParams(upQuery.parameters) + ");"); }); sqlInMemory.downQueries.forEach(downQuery => { - downSqls.push(" await queryRunner.query(`" + downQuery.query.replace(new RegExp("`", "g"), "\\`") + "`, " + JSON.stringify(downQuery.parameters) + ");"); + downSqls.push(" await queryRunner.query(`" + downQuery.query.replace(new RegExp("`", "g"), "\\`") + "`" + MigrationGenerateCommand.queryParams(downQuery.parameters) + ");"); }); } @@ -125,6 +141,17 @@ export class MigrationGenerateCommand implements yargs.CommandModule { // Protected Static Methods // ------------------------------------------------------------------------- + /** + * Formats query parameters for migration queries if parameters actually exist + */ + protected static queryParams(parameters: any[] | undefined): string { + if (!parameters || !parameters.length) { + return ""; + } + + return `, ${JSON.stringify(parameters)}`; + } + /** * Gets contents of the migration file. */ @@ -150,4 +177,11 @@ ${downSqls.join(` `; } + /** + * + */ + protected static prettifyQuery(query: string) { + const formattedQuery = format(query, { indent: " " }); + return "\n" + formattedQuery.replace(/^/gm, " ") + "\n "; + } } diff --git a/src/commands/MigrationRevertCommand.ts b/src/commands/MigrationRevertCommand.ts index dc978d20f3..1d70326c93 100644 --- a/src/commands/MigrationRevertCommand.ts +++ b/src/commands/MigrationRevertCommand.ts @@ -2,8 +2,7 @@ import {createConnection} from "../index"; import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import {Connection} from "../connection/Connection"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Reverts last migration command. diff --git a/src/commands/MigrationRunCommand.ts b/src/commands/MigrationRunCommand.ts index 37f2eddc9c..f953d5b551 100644 --- a/src/commands/MigrationRunCommand.ts +++ b/src/commands/MigrationRunCommand.ts @@ -3,8 +3,7 @@ import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import {Connection} from "../connection/Connection"; import * as process from "process"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Runs migration command. diff --git a/src/commands/MigrationShowCommand.ts b/src/commands/MigrationShowCommand.ts index 83328340a9..8995faa6b0 100644 --- a/src/commands/MigrationShowCommand.ts +++ b/src/commands/MigrationShowCommand.ts @@ -3,8 +3,7 @@ import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import {Connection} from "../connection/Connection"; import * as process from "process"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Runs migration command. diff --git a/src/commands/QueryCommand.ts b/src/commands/QueryCommand.ts index fe1bc897e3..3d705b9399 100644 --- a/src/commands/QueryCommand.ts +++ b/src/commands/QueryCommand.ts @@ -4,8 +4,7 @@ import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import {Connection} from "../connection/Connection"; import {PlatformTools} from "../platform/PlatformTools"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Executes an sql query on the given connection. @@ -49,7 +48,7 @@ export class QueryCommand implements yargs.CommandModule { connection = await createConnection(connectionOptions); // create a query runner and execute query using it - queryRunner = connection.createQueryRunner("master"); + queryRunner = connection.createQueryRunner(); console.log(chalk.green("Running query: ") + PlatformTools.highlightSql(args._[1])); const queryResult = await queryRunner.query(args._[1]); console.log(chalk.green("Query has been executed. Result: ")); diff --git a/src/commands/SchemaDropCommand.ts b/src/commands/SchemaDropCommand.ts index f88770f991..fcabb029c4 100644 --- a/src/commands/SchemaDropCommand.ts +++ b/src/commands/SchemaDropCommand.ts @@ -2,8 +2,7 @@ import {createConnection} from "../index"; import {Connection} from "../connection/Connection"; import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Drops all tables of the database from the given connection. diff --git a/src/commands/SchemaLogCommand.ts b/src/commands/SchemaLogCommand.ts index 86d99a0aac..73c1320934 100644 --- a/src/commands/SchemaLogCommand.ts +++ b/src/commands/SchemaLogCommand.ts @@ -3,8 +3,7 @@ import {Connection} from "../connection/Connection"; import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import {highlight} from "cli-highlight"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Shows sql to be executed by schema:sync command. @@ -53,7 +52,7 @@ export class SchemaLogCommand implements yargs.CommandModule { } else { const lengthSeparators = String(sqlInMemory.upQueries.length).split("").map(char => "-").join(""); console.log(chalk.yellow("---------------------------------------------------------------" + lengthSeparators)); - console.log(chalk.yellow.bold(`-- Schema syncronization will execute following sql queries (${chalk.white(sqlInMemory.upQueries.length)}):`)); + console.log(chalk.yellow.bold(`-- Schema syncronization will execute following sql queries (${chalk.white(sqlInMemory.upQueries.length.toString())}):`)); console.log(chalk.yellow("---------------------------------------------------------------" + lengthSeparators)); sqlInMemory.upQueries.forEach(upQuery => { diff --git a/src/commands/SchemaSyncCommand.ts b/src/commands/SchemaSyncCommand.ts index 7dcda016bf..3a1653344b 100644 --- a/src/commands/SchemaSyncCommand.ts +++ b/src/commands/SchemaSyncCommand.ts @@ -2,8 +2,7 @@ import {createConnection} from "../index"; import {Connection} from "../connection/Connection"; import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Synchronizes database schema with entities. diff --git a/src/commands/SubscriberCreateCommand.ts b/src/commands/SubscriberCreateCommand.ts index 9abff41753..65d908843d 100644 --- a/src/commands/SubscriberCreateCommand.ts +++ b/src/commands/SubscriberCreateCommand.ts @@ -1,8 +1,7 @@ import {ConnectionOptionsReader} from "../connection/ConnectionOptionsReader"; import {CommandUtils} from "./CommandUtils"; import * as yargs from "yargs"; - -const chalk = require("chalk"); +import chalk from "chalk"; /** * Generates a new subscriber. diff --git a/src/commands/VersionCommand.ts b/src/commands/VersionCommand.ts index 737444bb06..09361ea831 100644 --- a/src/commands/VersionCommand.ts +++ b/src/commands/VersionCommand.ts @@ -1,6 +1,5 @@ import * as yargs from "yargs"; - -const exec = require("child_process").exec; +import {exec} from "child_process"; /** * Shows typeorm version. diff --git a/src/common/DeepPartial.ts b/src/common/DeepPartial.ts index c318088d54..370c1f5f2d 100644 --- a/src/common/DeepPartial.ts +++ b/src/common/DeepPartial.ts @@ -5,5 +5,5 @@ export type DeepPartial = { [P in keyof T]?: T[P] extends Array ? Array> : T[P] extends ReadonlyArray ? ReadonlyArray> : - DeepPartial + DeepPartial | T[P] }; diff --git a/src/connection/Connection.ts b/src/connection/Connection.ts index ec3917318f..c95d70af7d 100644 --- a/src/connection/Connection.ts +++ b/src/connection/Connection.ts @@ -2,6 +2,7 @@ import {Driver} from "../driver/Driver"; import {QueryObserver} from "../observer/QueryObserver"; import {Repository} from "../repository/Repository"; import {EntitySubscriberInterface} from "../subscriber/EntitySubscriberInterface"; +import {EntityTarget} from "../common/EntityTarget"; import {ObjectType} from "../common/ObjectType"; import {EntityManager} from "../entity-manager/EntityManager"; import {DefaultNamingStrategy} from "../naming-strategy/DefaultNamingStrategy"; @@ -32,15 +33,16 @@ import {QueryResultCache} from "../cache/QueryResultCache"; import {SqljsEntityManager} from "../entity-manager/SqljsEntityManager"; import {RelationLoader} from "../query-builder/RelationLoader"; import {RelationIdLoader} from "../query-builder/RelationIdLoader"; -import {EntitySchema, PromiseUtils} from "../"; +import {EntitySchema} from "../"; import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver"; import {MysqlDriver} from "../driver/mysql/MysqlDriver"; import {ObjectUtils} from "../util/ObjectUtils"; import {IsolationLevel} from "../driver/types/IsolationLevel"; import {AuroraDataApiDriver} from "../driver/aurora-data-api/AuroraDataApiDriver"; +import {DriverUtils} from "../driver/DriverUtils"; +import {ReplicationMode} from "../driver/types/ReplicationMode"; import {EntityFactoryInterface} from "../entity-factory/EntityFactoryInterface"; import {DefaultEntityFactory} from "../entity-factory/DefaultEntityFactory"; -import {EntityTarget} from "../common/EntityTarget"; /** * Connection is a single database ORM connection to a specific database. @@ -286,7 +288,7 @@ export class Connection { */ // TODO rename async dropDatabase(): Promise { - const queryRunner = this.createQueryRunner("master"); + const queryRunner = this.createQueryRunner(); try { if (this.driver instanceof SqlServerDriver || this.driver instanceof MysqlDriver || this.driver instanceof AuroraDataApiDriver) { const databases: string[] = this.driver.database ? [this.driver.database] : []; @@ -294,7 +296,10 @@ export class Connection { if (metadata.database && databases.indexOf(metadata.database) === -1) databases.push(metadata.database); }); - await PromiseUtils.runInSequence(databases, database => queryRunner.clearDatabase(database)); + + for (const database of databases) { + await queryRunner.clearDatabase(database); + } } else { await queryRunner.clearDatabase(); } @@ -424,7 +429,7 @@ export class Connection { if (queryRunner && queryRunner.isReleased) throw new QueryRunnerProviderAlreadyReleasedError(); - const usedQueryRunner = queryRunner || this.createQueryRunner("master"); + const usedQueryRunner = queryRunner || this.createQueryRunner(); try { return await usedQueryRunner.query(query, parameters); // await is needed here because we are using finally @@ -453,7 +458,7 @@ export class Connection { throw new Error(`Query Builder is not supported by MongoDB.`); if (alias) { - const metadata = this.getMetadata(entityOrRunner as Function|EntitySchema|string); + const metadata = this.getMetadata(entityOrRunner as EntityTarget); return new SelectQueryBuilder(this, queryRunner) .select(alias) .from(metadata.target, alias); @@ -473,7 +478,7 @@ export class Connection { * If you perform writes you must use master database, * if you perform reads you can use slave databases. */ - createQueryRunner(mode: "master"|"slave" = "master"): QueryRunner { + createQueryRunner(mode: ReplicationMode = "master"): QueryRunner { const queryRunner = this.driver.createQueryRunner(mode); const manager = this.createEntityManager(queryRunner); Object.assign(queryRunner, { manager: manager }); @@ -483,7 +488,7 @@ export class Connection { /** * Gets entity metadata of the junction table (many-to-many table). */ - getManyToManyMetadata(entityTarget: Function|string, relationPropertyPath: string) { + getManyToManyMetadata(entityTarget: EntityTarget, relationPropertyPath: string) { const relationMetadata = this.getMetadata(entityTarget).findRelationWithPropertyPath(relationPropertyPath); if (!relationMetadata) throw new Error(`Relation "${relationPropertyPath}" was not found in ${entityTarget} entity.`); @@ -570,17 +575,17 @@ export class Connection { // This database name property is nested for replication configs. protected getDatabaseName(): string { - const options = this.options; - switch (options.type) { - case "mysql" : - case "mariadb" : - case "postgres": - case "cockroachdb": - case "mssql": - case "oracle": - return (options.replication ? options.replication.master.database : options.database) as string; - default: - return options.database as string; + const options = this.options; + switch (options.type) { + case "mysql" : + case "mariadb" : + case "postgres": + case "cockroachdb": + case "mssql": + case "oracle": + return DriverUtils.buildDriverOptions(options.replication ? options.replication.master : options).database; + default: + return DriverUtils.buildDriverOptions(options).database; } } diff --git a/src/connection/ConnectionOptions.ts b/src/connection/ConnectionOptions.ts index 2d223f74d6..40fd608087 100644 --- a/src/connection/ConnectionOptions.ts +++ b/src/connection/ConnectionOptions.ts @@ -12,6 +12,8 @@ import {NativescriptConnectionOptions} from "../driver/nativescript/Nativescript import {ExpoConnectionOptions} from "../driver/expo/ExpoConnectionOptions"; import {AuroraDataApiConnectionOptions} from "../driver/aurora-data-api/AuroraDataApiConnectionOptions"; import {SapConnectionOptions} from "../driver/sap/SapConnectionOptions"; +import {AuroraDataApiPostgresConnectionOptions} from "../driver/aurora-data-api-pg/AuroraDataApiPostgresConnectionOptions"; +import {BetterSqlite3ConnectionOptions} from "../driver/better-sqlite3/BetterSqlite3ConnectionOptions"; /** @@ -33,4 +35,6 @@ export type ConnectionOptions = SqljsConnectionOptions| MongoConnectionOptions| AuroraDataApiConnectionOptions| - ExpoConnectionOptions; + AuroraDataApiPostgresConnectionOptions| + ExpoConnectionOptions| + BetterSqlite3ConnectionOptions; diff --git a/src/connection/ConnectionOptionsReader.ts b/src/connection/ConnectionOptionsReader.ts index bfd2295183..997c240554 100644 --- a/src/connection/ConnectionOptionsReader.ts +++ b/src/connection/ConnectionOptionsReader.ts @@ -1,3 +1,4 @@ +import appRootPath from "app-root-path"; import {ConnectionOptions} from "./ConnectionOptions"; import {PlatformTools} from "../platform/PlatformTools"; import {ConnectionOptionsEnvReader} from "./options-reader/ConnectionOptionsEnvReader"; @@ -38,7 +39,7 @@ export class ConnectionOptionsReader { async all(): Promise { const options = await this.load(); if (!options) - throw new Error(`No connection options were found in any of configurations file.`); + throw new Error(`No connection options were found in any orm configuration files.`); return options; } @@ -80,7 +81,7 @@ export class ConnectionOptionsReader { protected async load(): Promise { let connectionOptions: ConnectionOptions|ConnectionOptions[]|undefined = undefined; - const fileFormats = ["env", "js", "ts", "json", "yml", "yaml", "xml"]; + const fileFormats = ["env", "js", "cjs", "ts", "json", "yml", "yaml", "xml"]; // Detect if baseFilePath contains file extension const possibleExtension = this.baseFilePath.substr(this.baseFilePath.lastIndexOf(".")); @@ -93,11 +94,9 @@ export class ConnectionOptionsReader { // if .env file found then load all its variables into process.env using dotenv package if (foundFileFormat === "env") { - const dotenv = PlatformTools.load("dotenv"); - dotenv.config({ path: this.baseFilePath }); + PlatformTools.dotenv(this.baseFilePath); } else if (PlatformTools.fileExist(".env")) { - const dotenv = PlatformTools.load("dotenv"); - dotenv.config({ path: ".env" }); + PlatformTools.dotenv(".env"); } // Determine config file name @@ -107,14 +106,14 @@ export class ConnectionOptionsReader { if (PlatformTools.getEnvVariable("TYPEORM_CONNECTION") || PlatformTools.getEnvVariable("TYPEORM_URL")) { connectionOptions = new ConnectionOptionsEnvReader().read(); - } else if (foundFileFormat === "js") { - connectionOptions = await PlatformTools.load(configFile); + } else if (foundFileFormat === "js" || foundFileFormat === "cjs") { + connectionOptions = await require(configFile); } else if (foundFileFormat === "ts") { - connectionOptions = await PlatformTools.load(configFile); + connectionOptions = await require(configFile); } else if (foundFileFormat === "json") { - connectionOptions = PlatformTools.load(configFile); + connectionOptions = require(configFile); } else if (foundFileFormat === "yml") { connectionOptions = new ConnectionOptionsYmlReader().read(configFile); @@ -171,7 +170,7 @@ export class ConnectionOptionsReader { } // make database path file in sqlite relative to package.json - if (options.type === "sqlite") { + if (options.type === "sqlite" || options.type === "better-sqlite3") { if (typeof options.database === "string" && options.database.substr(0, 1) !== "/" && // unix absolute options.database.substr(1, 2) !== ":\\" && // windows absolute @@ -200,7 +199,7 @@ export class ConnectionOptionsReader { if (this.options && this.options.root) return this.options.root; - return PlatformTools.load("app-root-path").path; + return appRootPath.path; } /** diff --git a/src/connection/options-reader/ConnectionOptionsXmlReader.ts b/src/connection/options-reader/ConnectionOptionsXmlReader.ts index d43e9e7644..17f5cf347e 100644 --- a/src/connection/options-reader/ConnectionOptionsXmlReader.ts +++ b/src/connection/options-reader/ConnectionOptionsXmlReader.ts @@ -1,3 +1,4 @@ +import {parseString as xmlParser} from 'xml2js'; import {PlatformTools} from "../../platform/PlatformTools"; import {ConnectionOptions} from "../ConnectionOptions"; @@ -43,11 +44,10 @@ export class ConnectionOptionsXmlReader { * Reads xml file contents and returns them in a promise. */ protected readXml(path: string): Promise { - const xmlParser = PlatformTools.load("xml2js").parseString; const xmlOptions = { trim: true, explicitRoot: false }; return new Promise((ok, fail) => { xmlParser(PlatformTools.readFileSync(path), xmlOptions, (err: any, result: any) => err ? fail(err) : ok(result)); }); } -} \ No newline at end of file +} diff --git a/src/connection/options-reader/ConnectionOptionsYmlReader.ts b/src/connection/options-reader/ConnectionOptionsYmlReader.ts index 8d90e6a519..7c14a4d28f 100644 --- a/src/connection/options-reader/ConnectionOptionsYmlReader.ts +++ b/src/connection/options-reader/ConnectionOptionsYmlReader.ts @@ -1,3 +1,4 @@ +import ymlParser from 'js-yaml'; import {PlatformTools} from "../../platform/PlatformTools"; import {ConnectionOptions} from "../ConnectionOptions"; @@ -14,11 +15,18 @@ export class ConnectionOptionsYmlReader { * Reads connection options from given yml file. */ read(path: string): ConnectionOptions[] { - const ymlParser = PlatformTools.load("js-yaml"); - const config = ymlParser.safeLoad(PlatformTools.readFileSync(path)); + const contentsBuffer = PlatformTools.readFileSync(path); + const contents = contentsBuffer.toString(); + + const config: undefined | string | {[key: string]: any} = ymlParser.safeLoad(contents); + + if (typeof config !== 'object') { + return []; + } + return Object.keys(config).map(connectionName => { return Object.assign({ name: connectionName }, config[connectionName]); }); } -} \ No newline at end of file +} diff --git a/src/decorator/Check.ts b/src/decorator/Check.ts index 138eea1174..305fd1e5b8 100644 --- a/src/decorator/Check.ts +++ b/src/decorator/Check.ts @@ -6,21 +6,21 @@ import {CheckMetadataArgs} from "../metadata-args/CheckMetadataArgs"; * Can be used on entity property or on entity. * Can create checks with composite columns when used on entity. */ -export function Check(expression: string): Function; +export function Check(expression: string): ClassDecorator & PropertyDecorator; /** * Creates a database check. * Can be used on entity property or on entity. * Can create checks with composite columns when used on entity. */ -export function Check(name: string, expression: string): Function; +export function Check(name: string, expression: string): ClassDecorator & PropertyDecorator; /** * Creates a database check. * Can be used on entity property or on entity. * Can create checks with composite columns when used on entity. */ -export function Check(nameOrExpression: string, maybeExpression?: string): Function { +export function Check(nameOrExpression: string, maybeExpression?: string): ClassDecorator & PropertyDecorator { const name = maybeExpression ? nameOrExpression : undefined; const expression = maybeExpression ? maybeExpression : nameOrExpression; @@ -28,7 +28,7 @@ export function Check(nameOrExpression: string, maybeExpression?: string): Funct if (!expression) throw new Error(`Check expression is required`); - return function (clsOrObject: Function|Object, propertyName?: string) { + return function (clsOrObject: Function|Object, propertyName?: string | symbol) { getMetadataArgsStorage().checks.push({ target: propertyName ? clsOrObject.constructor : clsOrObject as Function, diff --git a/src/decorator/EntityRepository.ts b/src/decorator/EntityRepository.ts index 092f4c1218..3a25adcdd0 100644 --- a/src/decorator/EntityRepository.ts +++ b/src/decorator/EntityRepository.ts @@ -7,7 +7,7 @@ import {EntitySchema} from "../entity-schema/EntitySchema"; * Custom repository can manage some specific entity or just be generic. * Custom repository optionally can extend AbstractRepository, Repository or TreeRepository. */ -export function EntityRepository(entity?: Function | EntitySchema): Function { +export function EntityRepository(entity?: Function | EntitySchema): ClassDecorator { return function (target: Function) { getMetadataArgsStorage().entityRepositories.push({ diff --git a/src/decorator/Exclusion.ts b/src/decorator/Exclusion.ts index 75f3434a94..d05394cab8 100644 --- a/src/decorator/Exclusion.ts +++ b/src/decorator/Exclusion.ts @@ -6,21 +6,21 @@ import {ExclusionMetadataArgs} from "../metadata-args/ExclusionMetadataArgs"; * Can be used on entity. * Can create exclusions with composite columns when used on entity. */ -export function Exclusion(expression: string): Function; +export function Exclusion(expression: string): ClassDecorator & PropertyDecorator; /** * Creates a database exclusion. * Can be used on entity. * Can create exclusions with composite columns when used on entity. */ -export function Exclusion(name: string, expression: string): Function; +export function Exclusion(name: string, expression: string): ClassDecorator & PropertyDecorator; /** * Creates a database exclusion. * Can be used on entity. * Can create exclusions with composite columns when used on entity. */ -export function Exclusion(nameOrExpression: string, maybeExpression?: string): Function { +export function Exclusion(nameOrExpression: string, maybeExpression?: string): ClassDecorator & PropertyDecorator { const name = maybeExpression ? nameOrExpression : undefined; const expression = maybeExpression ? maybeExpression : nameOrExpression; @@ -28,7 +28,7 @@ export function Exclusion(nameOrExpression: string, maybeExpression?: string): F if (!expression) throw new Error(`Exclusion expression is required`); - return function (clsOrObject: Function|Object, propertyName?: string) { + return function (clsOrObject: Function|Object, propertyName?: string | symbol) { getMetadataArgsStorage().exclusions.push({ target: propertyName ? clsOrObject.constructor : clsOrObject as Function, diff --git a/src/decorator/Generated.ts b/src/decorator/Generated.ts index 9857c95e49..934ccd4b6c 100644 --- a/src/decorator/Generated.ts +++ b/src/decorator/Generated.ts @@ -10,7 +10,7 @@ import {GeneratedMetadataArgs} from "../metadata-args/GeneratedMetadataArgs"; * * Note, some databases do not support non-primary generation columns. */ -export function Generated(strategy: "increment"|"uuid"|"rowid" = "increment"): Function { +export function Generated(strategy: "increment"|"uuid"|"rowid" = "increment"): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().generations.push({ diff --git a/src/decorator/Index.ts b/src/decorator/Index.ts index 17e57ea5c0..2bc63d6826 100644 --- a/src/decorator/Index.ts +++ b/src/decorator/Index.ts @@ -6,49 +6,49 @@ import {IndexMetadataArgs} from "../metadata-args/IndexMetadataArgs"; * Can be used on entity property or on entity. * Can create indices with composite columns when used on entity. */ -export function Index(options?: IndexOptions): Function; +export function Index(options?: IndexOptions): ClassDecorator & PropertyDecorator; /** * Creates a database index. * Can be used on entity property or on entity. * Can create indices with composite columns when used on entity. */ -export function Index(name: string, options?: IndexOptions): Function; +export function Index(name: string, options?: IndexOptions): ClassDecorator & PropertyDecorator; /** * Creates a database index. * Can be used on entity property or on entity. * Can create indices with composite columns when used on entity. */ -export function Index(name: string, options: { synchronize: false }): Function; +export function Index(name: string, options: { synchronize: false }): ClassDecorator & PropertyDecorator; /** * Creates a database index. * Can be used on entity property or on entity. * Can create indices with composite columns when used on entity. */ -export function Index(name: string, fields: string[], options?: IndexOptions): Function; +export function Index(name: string, fields: string[], options?: IndexOptions): ClassDecorator & PropertyDecorator; /** * Creates a database index. * Can be used on entity property or on entity. * Can create indices with composite columns when used on entity. */ -export function Index(fields: string[], options?: IndexOptions): Function; +export function Index(fields: string[], options?: IndexOptions): ClassDecorator & PropertyDecorator; /** * Creates a database index. * Can be used on entity property or on entity. * Can create indices with composite columns when used on entity. */ -export function Index(fields: (object?: any) => (any[]|{ [key: string]: number }), options?: IndexOptions): Function; +export function Index(fields: (object?: any) => (any[]|{ [key: string]: number }), options?: IndexOptions): ClassDecorator & PropertyDecorator; /** * Creates a database index. * Can be used on entity property or on entity. * Can create indices with composite columns when used on entity. */ -export function Index(name: string, fields: (object?: any) => (any[]|{ [key: string]: number }), options?: IndexOptions): Function; +export function Index(name: string, fields: (object?: any) => (any[]|{ [key: string]: number }), options?: IndexOptions): ClassDecorator & PropertyDecorator; /** * Creates a database index. @@ -57,7 +57,7 @@ export function Index(name: string, fields: (object?: any) => (any[]|{ [key: str */ export function Index(nameOrFieldsOrOptions?: string|string[]|((object: any) => (any[]|{ [key: string]: number }))|IndexOptions, maybeFieldsOrOptions?: ((object?: any) => (any[]|{ [key: string]: number }))|IndexOptions|string[]|{ synchronize: false }, - maybeOptions?: IndexOptions): Function { + maybeOptions?: IndexOptions): ClassDecorator & PropertyDecorator { // normalize parameters const name = typeof nameOrFieldsOrOptions === "string" ? nameOrFieldsOrOptions : undefined; @@ -66,7 +66,7 @@ export function Index(nameOrFieldsOrOptions?: string|string[]|((object: any) => if (!options) options = (typeof maybeFieldsOrOptions === "object" && !Array.isArray(maybeFieldsOrOptions)) ? maybeFieldsOrOptions as IndexOptions : maybeOptions; - return function (clsOrObject: Function|Object, propertyName?: string) { + return function (clsOrObject: Function|Object, propertyName?: string | symbol) { getMetadataArgsStorage().indices.push({ target: propertyName ? clsOrObject.constructor : clsOrObject as Function, diff --git a/src/decorator/Unique.ts b/src/decorator/Unique.ts index 871e25c58a..1923af52ad 100644 --- a/src/decorator/Unique.ts +++ b/src/decorator/Unique.ts @@ -1,39 +1,54 @@ -import {getMetadataArgsStorage} from "../index"; -import {UniqueMetadataArgs} from "../metadata-args/UniqueMetadataArgs"; +import { getMetadataArgsStorage } from "../index"; +import { UniqueMetadataArgs } from "../metadata-args/UniqueMetadataArgs"; /** * Composite unique constraint must be set on entity classes and must specify entity's fields to be unique. */ -export function Unique(name: string, fields: string[]): Function; +export function Unique(name: string, fields: string[]): ClassDecorator & PropertyDecorator; /** * Composite unique constraint must be set on entity classes and must specify entity's fields to be unique. */ -export function Unique(fields: string[]): Function; +export function Unique(fields: string[]): ClassDecorator & PropertyDecorator; /** * Composite unique constraint must be set on entity classes and must specify entity's fields to be unique. */ -export function Unique(fields: (object?: any) => (any[]|{ [key: string]: number })): Function; +export function Unique(fields: (object?: any) => (any[] | { [key: string]: number })): ClassDecorator & PropertyDecorator; /** * Composite unique constraint must be set on entity classes and must specify entity's fields to be unique. */ -export function Unique(name: string, fields: (object?: any) => (any[]|{ [key: string]: number })): Function; +export function Unique(name: string, fields: (object?: any) => (any[] | { [key: string]: number })): ClassDecorator & PropertyDecorator; /** * Composite unique constraint must be set on entity classes and must specify entity's fields to be unique. */ -export function Unique(nameOrFields?: string|string[]|((object: any) => (any[]|{ [key: string]: number })), - maybeFields?: ((object?: any) => (any[]|{ [key: string]: number }))|string[]): Function { +export function Unique(nameOrFields?: string | string[] | ((object: any) => (any[] | { [key: string]: number })), + maybeFields?: ((object?: any) => (any[] | { [key: string]: number })) | string[]): ClassDecorator & PropertyDecorator { const name = typeof nameOrFields === "string" ? nameOrFields : undefined; - const fields = typeof nameOrFields === "string" ? <((object?: any) => (any[]|{ [key: string]: number }))|string[]> maybeFields : nameOrFields as string[]; + const fields = typeof nameOrFields === "string" ? <((object?: any) => (any[] | { [key: string]: number })) | string[]>maybeFields : nameOrFields as string[]; + + return function (clsOrObject: Function | Object, propertyName?: string | symbol) { + + let columns = fields; + + if (propertyName !== undefined) { + switch (typeof (propertyName)) { + case "string": + columns = [propertyName]; + break; + + case "symbol": + columns = [propertyName.toString()]; + break; + } + } - return function (clsOrObject: Function|Object, propertyName?: string) { const args: UniqueMetadataArgs = { target: propertyName ? clsOrObject.constructor : clsOrObject as Function, name: name, - columns: propertyName ? [propertyName] : fields + columns, }; getMetadataArgsStorage().uniques.push(args); }; diff --git a/src/decorator/columns/Column.ts b/src/decorator/columns/Column.ts index 457f548d81..ac5467980c 100644 --- a/src/decorator/columns/Column.ts +++ b/src/decorator/columns/Column.ts @@ -24,67 +24,67 @@ import {GeneratedMetadataArgs} from "../../metadata-args/GeneratedMetadataArgs"; * Column decorator is used to mark a specific class property as a table column. Only properties decorated with this * decorator will be persisted to the database when entity be saved. */ -export function Column(): Function; +export function Column(): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(options: ColumnOptions): Function; +export function Column(options: ColumnOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(type: SimpleColumnType, options?: ColumnCommonOptions): Function; +export function Column(type: SimpleColumnType, options?: ColumnCommonOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(type: SpatialColumnType, options?: ColumnCommonOptions & SpatialColumnOptions): Function; +export function Column(type: SpatialColumnType, options?: ColumnCommonOptions & SpatialColumnOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(type: WithLengthColumnType, options?: ColumnCommonOptions & ColumnWithLengthOptions): Function; +export function Column(type: WithLengthColumnType, options?: ColumnCommonOptions & ColumnWithLengthOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(type: WithWidthColumnType, options?: ColumnCommonOptions & ColumnWithWidthOptions): Function; +export function Column(type: WithWidthColumnType, options?: ColumnCommonOptions & ColumnWithWidthOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(type: WithPrecisionColumnType, options?: ColumnCommonOptions & ColumnNumericOptions): Function; +export function Column(type: WithPrecisionColumnType, options?: ColumnCommonOptions & ColumnNumericOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(type: "enum", options?: ColumnCommonOptions & ColumnEnumOptions): Function; +export function Column(type: "enum", options?: ColumnCommonOptions & ColumnEnumOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(type: "simple-enum", options?: ColumnCommonOptions & ColumnEnumOptions): Function; +export function Column(type: "simple-enum", options?: ColumnCommonOptions & ColumnEnumOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(type: "set", options?: ColumnCommonOptions & ColumnEnumOptions): Function; +export function Column(type: "set", options?: ColumnCommonOptions & ColumnEnumOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(type: "hstore", options?: ColumnCommonOptions & ColumnHstoreOptions): Function; +export function Column(type: "hstore", options?: ColumnCommonOptions & ColumnHstoreOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. @@ -94,13 +94,13 @@ export function Column(type: "hstore", options?: ColumnCommonOptions & ColumnHst * single table of the entity where Embedded is used. And on hydration all columns which supposed to be in the * embedded will be mapped to it from the single table. */ -export function Column(type: (type?: any) => Function, options?: ColumnEmbeddedOptions): Function; +export function Column(type: (type?: any) => Function, options?: ColumnEmbeddedOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. */ -export function Column(typeOrOptions?: ((type?: any) => Function)|ColumnType|(ColumnOptions&ColumnEmbeddedOptions), options?: (ColumnOptions&ColumnEmbeddedOptions)): Function { +export function Column(typeOrOptions?: ((type?: any) => Function)|ColumnType|(ColumnOptions&ColumnEmbeddedOptions), options?: (ColumnOptions&ColumnEmbeddedOptions)): PropertyDecorator { return function (object: Object, propertyName: string) { // normalize parameters diff --git a/src/decorator/columns/CreateDateColumn.ts b/src/decorator/columns/CreateDateColumn.ts index 6d9acd802d..b14bf5c4f3 100644 --- a/src/decorator/columns/CreateDateColumn.ts +++ b/src/decorator/columns/CreateDateColumn.ts @@ -6,7 +6,7 @@ import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs"; * Creation date is generated and inserted only once, * at the first time when you create an object, the value is inserted into the table, and is never touched again. */ -export function CreateDateColumn(options?: ColumnOptions): Function { +export function CreateDateColumn(options?: ColumnOptions): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().columns.push({ target: object.constructor, diff --git a/src/decorator/columns/DeleteDateColumn.ts b/src/decorator/columns/DeleteDateColumn.ts index 35ea43b848..deece8bba0 100644 --- a/src/decorator/columns/DeleteDateColumn.ts +++ b/src/decorator/columns/DeleteDateColumn.ts @@ -5,7 +5,7 @@ import { ColumnMetadataArgs } from "../../metadata-args/ColumnMetadataArgs"; * This column will store a delete date of the soft-deleted object. * This date is being updated each time you soft-delete the object. */ -export function DeleteDateColumn(options?: ColumnOptions): Function { +export function DeleteDateColumn(options?: ColumnOptions): PropertyDecorator { return function(object: Object, propertyName: string) { getMetadataArgsStorage().columns.push({ target: object.constructor, diff --git a/src/decorator/columns/ObjectIdColumn.ts b/src/decorator/columns/ObjectIdColumn.ts index 257aebf347..5feeb201de 100644 --- a/src/decorator/columns/ObjectIdColumn.ts +++ b/src/decorator/columns/ObjectIdColumn.ts @@ -5,7 +5,7 @@ import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs"; * Special type of column that is available only for MongoDB database. * Marks your entity's column to be an object id. */ -export function ObjectIdColumn(options?: ColumnOptions): Function { +export function ObjectIdColumn(options?: ColumnOptions): PropertyDecorator { return function (object: Object, propertyName: string) { // if column options are not given then create a new empty options diff --git a/src/decorator/columns/PrimaryColumn.ts b/src/decorator/columns/PrimaryColumn.ts index d47ec1748e..e84b8d12ba 100644 --- a/src/decorator/columns/PrimaryColumn.ts +++ b/src/decorator/columns/PrimaryColumn.ts @@ -9,21 +9,21 @@ import {GeneratedMetadataArgs} from "../../metadata-args/GeneratedMetadataArgs"; * Only properties decorated with this decorator will be persisted to the database when entity be saved. * Primary columns also creates a PRIMARY KEY for this column in a db. */ -export function PrimaryColumn(options?: ColumnOptions): Function; +export function PrimaryColumn(options?: ColumnOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. * Primary columns also creates a PRIMARY KEY for this column in a db. */ -export function PrimaryColumn(type?: ColumnType, options?: ColumnOptions): Function; +export function PrimaryColumn(type?: ColumnType, options?: ColumnOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. * Only properties decorated with this decorator will be persisted to the database when entity be saved. * Primary columns also creates a PRIMARY KEY for this column in a db. */ -export function PrimaryColumn(typeOrOptions?: ColumnType|ColumnOptions, options?: ColumnOptions): Function { +export function PrimaryColumn(typeOrOptions?: ColumnType|ColumnOptions, options?: ColumnOptions): PropertyDecorator { return function (object: Object, propertyName: string) { // normalize parameters diff --git a/src/decorator/columns/PrimaryGeneratedColumn.ts b/src/decorator/columns/PrimaryGeneratedColumn.ts index afa6c81336..14fbffa55a 100644 --- a/src/decorator/columns/PrimaryGeneratedColumn.ts +++ b/src/decorator/columns/PrimaryGeneratedColumn.ts @@ -6,27 +6,27 @@ import {GeneratedMetadataArgs} from "../../metadata-args/GeneratedMetadataArgs"; /** * Column decorator is used to mark a specific class property as a table column. */ -export function PrimaryGeneratedColumn(): Function; +export function PrimaryGeneratedColumn(): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. */ -export function PrimaryGeneratedColumn(options: PrimaryGeneratedColumnNumericOptions): Function; +export function PrimaryGeneratedColumn(options: PrimaryGeneratedColumnNumericOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. */ -export function PrimaryGeneratedColumn(strategy: "increment", options?: PrimaryGeneratedColumnNumericOptions): Function; +export function PrimaryGeneratedColumn(strategy: "increment", options?: PrimaryGeneratedColumnNumericOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. */ -export function PrimaryGeneratedColumn(strategy: "uuid", options?: PrimaryGeneratedColumnUUIDOptions): Function; +export function PrimaryGeneratedColumn(strategy: "uuid", options?: PrimaryGeneratedColumnUUIDOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. */ -export function PrimaryGeneratedColumn(strategy: "rowid", options?: PrimaryGeneratedColumnUUIDOptions): Function; +export function PrimaryGeneratedColumn(strategy: "rowid", options?: PrimaryGeneratedColumnUUIDOptions): PropertyDecorator; /** * Column decorator is used to mark a specific class property as a table column. @@ -34,7 +34,7 @@ export function PrimaryGeneratedColumn(strategy: "rowid", options?: PrimaryGener * This column creates an integer PRIMARY COLUMN with generated set to true. */ export function PrimaryGeneratedColumn(strategyOrOptions?: "increment"|"uuid"|"rowid"|PrimaryGeneratedColumnNumericOptions|PrimaryGeneratedColumnUUIDOptions, - maybeOptions?: PrimaryGeneratedColumnNumericOptions|PrimaryGeneratedColumnUUIDOptions): Function { + maybeOptions?: PrimaryGeneratedColumnNumericOptions|PrimaryGeneratedColumnUUIDOptions): PropertyDecorator { // normalize parameters const options: ColumnOptions = {}; diff --git a/src/decorator/columns/UpdateDateColumn.ts b/src/decorator/columns/UpdateDateColumn.ts index f4895e76b4..f4627a0df4 100644 --- a/src/decorator/columns/UpdateDateColumn.ts +++ b/src/decorator/columns/UpdateDateColumn.ts @@ -5,7 +5,7 @@ import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs"; * This column will store an update date of the updated object. * This date is being updated each time you persist the object. */ -export function UpdateDateColumn(options?: ColumnOptions): Function { +export function UpdateDateColumn(options?: ColumnOptions): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().columns.push({ diff --git a/src/decorator/columns/VersionColumn.ts b/src/decorator/columns/VersionColumn.ts index f1f14984a3..1779869783 100644 --- a/src/decorator/columns/VersionColumn.ts +++ b/src/decorator/columns/VersionColumn.ts @@ -6,7 +6,7 @@ import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs"; * Every time your entity will be persisted, this number will be increased by one - * so you can organize visioning and update strategies of your entity. */ -export function VersionColumn(options?: ColumnOptions): Function { +export function VersionColumn(options?: ColumnOptions): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().columns.push({ diff --git a/src/decorator/columns/ViewColumn.ts b/src/decorator/columns/ViewColumn.ts index 998af7bfbd..11356f66e3 100644 --- a/src/decorator/columns/ViewColumn.ts +++ b/src/decorator/columns/ViewColumn.ts @@ -1,16 +1,17 @@ import {getMetadataArgsStorage} from "../../"; import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs"; +import { ViewColumnOptions } from "../options/ViewColumnOptions"; /** * ViewColumn decorator is used to mark a specific class property as a view column. */ -export function ViewColumn(): Function { +export function ViewColumn(options?: ViewColumnOptions): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().columns.push({ target: object.constructor, propertyName: propertyName, mode: "regular", - options: {} + options: options || {} } as ColumnMetadataArgs); }; } diff --git a/src/decorator/entity-view/ViewEntity.ts b/src/decorator/entity-view/ViewEntity.ts index 50cb0f96a4..7223ed8ce5 100644 --- a/src/decorator/entity-view/ViewEntity.ts +++ b/src/decorator/entity-view/ViewEntity.ts @@ -6,19 +6,19 @@ import {ViewEntityOptions} from "../options/ViewEntityOptions"; * This decorator is used to mark classes that will be an entity view. * Database schema will be created for all classes decorated with it, and Repository can be retrieved and used for it. */ -export function ViewEntity(options?: ViewEntityOptions): Function; +export function ViewEntity(options?: ViewEntityOptions): ClassDecorator; /** * This decorator is used to mark classes that will be an entity view. * Database schema will be created for all classes decorated with it, and Repository can be retrieved and used for it. */ -export function ViewEntity(name?: string, options?: ViewEntityOptions): Function; +export function ViewEntity(name?: string, options?: ViewEntityOptions): ClassDecorator; /** * This decorator is used to mark classes that will be an entity view. * Database schema will be created for all classes decorated with it, and Repository can be retrieved and used for it. */ -export function ViewEntity(nameOrOptions?: string|ViewEntityOptions, maybeOptions?: ViewEntityOptions): Function { +export function ViewEntity(nameOrOptions?: string|ViewEntityOptions, maybeOptions?: ViewEntityOptions): ClassDecorator { const options = (typeof nameOrOptions === "object" ? nameOrOptions as ViewEntityOptions : maybeOptions) || {}; const name = typeof nameOrOptions === "string" ? nameOrOptions : options.name; diff --git a/src/decorator/entity/ChildEntity.ts b/src/decorator/entity/ChildEntity.ts index 644b7d5bab..aee1b9746a 100644 --- a/src/decorator/entity/ChildEntity.ts +++ b/src/decorator/entity/ChildEntity.ts @@ -5,7 +5,7 @@ import {DiscriminatorValueMetadataArgs} from "../../metadata-args/DiscriminatorV /** * Special type of the table used in the single-table inherited tables. */ -export function ChildEntity(discriminatorValue?: any) { +export function ChildEntity(discriminatorValue?: any): ClassDecorator { return function (target: Function) { // register a table metadata diff --git a/src/decorator/entity/Entity.ts b/src/decorator/entity/Entity.ts index bb2af675d0..f90e446470 100644 --- a/src/decorator/entity/Entity.ts +++ b/src/decorator/entity/Entity.ts @@ -5,23 +5,23 @@ import {TableMetadataArgs} from "../../metadata-args/TableMetadataArgs"; * This decorator is used to mark classes that will be an entity (table or document depend on database type). * Database schema will be created for all classes decorated with it, and Repository can be retrieved and used for it. */ -export function Entity(options?: EntityOptions): Function; +export function Entity(options?: EntityOptions): ClassDecorator; /** * This decorator is used to mark classes that will be an entity (table or document depend on database type). * Database schema will be created for all classes decorated with it, and Repository can be retrieved and used for it. */ -export function Entity(name?: string, options?: EntityOptions): Function; +export function Entity(name?: string, options?: EntityOptions): ClassDecorator; /** * This decorator is used to mark classes that will be an entity (table or document depend on database type). * Database schema will be created for all classes decorated with it, and Repository can be retrieved and used for it. */ -export function Entity(nameOrOptions?: string|EntityOptions, maybeOptions?: EntityOptions): Function { +export function Entity(nameOrOptions?: string|EntityOptions, maybeOptions?: EntityOptions): ClassDecorator { const options = (typeof nameOrOptions === "object" ? nameOrOptions as EntityOptions : maybeOptions) || {}; const name = typeof nameOrOptions === "string" ? nameOrOptions : options.name; - return function (target: Function) { + return function (target) { getMetadataArgsStorage().tables.push({ target: target, name: name, diff --git a/src/decorator/entity/TableInheritance.ts b/src/decorator/entity/TableInheritance.ts index 264743713e..f716b5c227 100644 --- a/src/decorator/entity/TableInheritance.ts +++ b/src/decorator/entity/TableInheritance.ts @@ -4,7 +4,7 @@ import {InheritanceMetadataArgs} from "../../metadata-args/InheritanceMetadataAr /** * Sets for entity to use table inheritance pattern. */ -export function TableInheritance(options?: { pattern?: "STI"/*|"CTI"*/, column?: string|ColumnOptions }) { +export function TableInheritance(options?: { pattern?: "STI"/*|"CTI"*/, column?: string|ColumnOptions }): ClassDecorator { return function (target: Function) { getMetadataArgsStorage().inheritances.push({ diff --git a/src/decorator/listeners/AfterInsert.ts b/src/decorator/listeners/AfterInsert.ts index 68c2c1a11c..48be17d67d 100644 --- a/src/decorator/listeners/AfterInsert.ts +++ b/src/decorator/listeners/AfterInsert.ts @@ -5,7 +5,7 @@ import {EntityListenerMetadataArgs} from "../../metadata-args/EntityListenerMeta /** * Calls a method on which this decorator is applied after this entity insertion. */ -export function AfterInsert() { +export function AfterInsert(): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().entityListeners.push({ diff --git a/src/decorator/listeners/AfterLoad.ts b/src/decorator/listeners/AfterLoad.ts index 8b810feed7..02e2fe81c6 100644 --- a/src/decorator/listeners/AfterLoad.ts +++ b/src/decorator/listeners/AfterLoad.ts @@ -5,7 +5,7 @@ import {EntityListenerMetadataArgs} from "../../metadata-args/EntityListenerMeta /** * Calls a method on which this decorator is applied after entity is loaded. */ -export function AfterLoad() { +export function AfterLoad(): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().entityListeners.push({ diff --git a/src/decorator/listeners/AfterRemove.ts b/src/decorator/listeners/AfterRemove.ts index e9e7d2549c..a2f00f63f4 100644 --- a/src/decorator/listeners/AfterRemove.ts +++ b/src/decorator/listeners/AfterRemove.ts @@ -5,7 +5,7 @@ import {EntityListenerMetadataArgs} from "../../metadata-args/EntityListenerMeta /** * Calls a method on which this decorator is applied after this entity removal. */ -export function AfterRemove() { +export function AfterRemove(): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().entityListeners.push({ diff --git a/src/decorator/listeners/AfterUpdate.ts b/src/decorator/listeners/AfterUpdate.ts index fadb31815f..f77241e095 100644 --- a/src/decorator/listeners/AfterUpdate.ts +++ b/src/decorator/listeners/AfterUpdate.ts @@ -5,7 +5,7 @@ import {EntityListenerMetadataArgs} from "../../metadata-args/EntityListenerMeta /** * Calls a method on which this decorator is applied after this entity update. */ -export function AfterUpdate() { +export function AfterUpdate(): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().entityListeners.push({ diff --git a/src/decorator/listeners/BeforeInsert.ts b/src/decorator/listeners/BeforeInsert.ts index 10db63ad14..6f2d4c7d98 100644 --- a/src/decorator/listeners/BeforeInsert.ts +++ b/src/decorator/listeners/BeforeInsert.ts @@ -5,7 +5,7 @@ import {EntityListenerMetadataArgs} from "../../metadata-args/EntityListenerMeta /** * Calls a method on which this decorator is applied before this entity insertion. */ -export function BeforeInsert() { +export function BeforeInsert(): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().entityListeners.push({ diff --git a/src/decorator/listeners/BeforeRemove.ts b/src/decorator/listeners/BeforeRemove.ts index e108e2e9f6..0fcadd1fa4 100644 --- a/src/decorator/listeners/BeforeRemove.ts +++ b/src/decorator/listeners/BeforeRemove.ts @@ -5,7 +5,7 @@ import {EntityListenerMetadataArgs} from "../../metadata-args/EntityListenerMeta /** * Calls a method on which this decorator is applied before this entity removal. */ -export function BeforeRemove() { +export function BeforeRemove(): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().entityListeners.push({ diff --git a/src/decorator/listeners/BeforeUpdate.ts b/src/decorator/listeners/BeforeUpdate.ts index 753e3a1532..d4a15d36d2 100644 --- a/src/decorator/listeners/BeforeUpdate.ts +++ b/src/decorator/listeners/BeforeUpdate.ts @@ -5,7 +5,7 @@ import {EntityListenerMetadataArgs} from "../../metadata-args/EntityListenerMeta /** * Calls a method on which this decorator is applied before this entity update. */ -export function BeforeUpdate() { +export function BeforeUpdate(): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().entityListeners.push({ diff --git a/src/decorator/listeners/EventSubscriber.ts b/src/decorator/listeners/EventSubscriber.ts index 99741d0b9a..ea13dc44a8 100644 --- a/src/decorator/listeners/EventSubscriber.ts +++ b/src/decorator/listeners/EventSubscriber.ts @@ -5,7 +5,7 @@ import {EntitySubscriberMetadataArgs} from "../../metadata-args/EntitySubscriber * Classes decorated with this decorator will listen to ORM events and their methods will be triggered when event * occurs. Those classes must implement EventSubscriberInterface interface. */ -export function EventSubscriber() { +export function EventSubscriber(): ClassDecorator { return function (target: Function) { getMetadataArgsStorage().entitySubscribers.push({ diff --git a/src/decorator/options/ViewColumnOptions.ts b/src/decorator/options/ViewColumnOptions.ts new file mode 100644 index 0000000000..a2b132cd61 --- /dev/null +++ b/src/decorator/options/ViewColumnOptions.ts @@ -0,0 +1,9 @@ +/** + * Describes all view column's options. + */ +export interface ViewColumnOptions { + /** + * Column name in the database. + */ + name?: string; +} diff --git a/src/decorator/relations/JoinColumn.ts b/src/decorator/relations/JoinColumn.ts index 3bded3a080..f619e374ad 100644 --- a/src/decorator/relations/JoinColumn.ts +++ b/src/decorator/relations/JoinColumn.ts @@ -6,28 +6,28 @@ import {JoinColumnMetadataArgs} from "../../metadata-args/JoinColumnMetadataArgs * It also can be used on both one-to-one and many-to-one relations to specify custom column name * or custom referenced column. */ -export function JoinColumn(): Function; +export function JoinColumn(): PropertyDecorator; /** * JoinColumn decorator used on one-to-one relations to specify owner side of relationship. * It also can be used on both one-to-one and many-to-one relations to specify custom column name * or custom referenced column. */ -export function JoinColumn(options: JoinColumnOptions): Function; +export function JoinColumn(options: JoinColumnOptions): PropertyDecorator; /** * JoinColumn decorator used on one-to-one relations to specify owner side of relationship. * It also can be used on both one-to-one and many-to-one relations to specify custom column name * or custom referenced column. */ -export function JoinColumn(options: JoinColumnOptions[]): Function; +export function JoinColumn(options: JoinColumnOptions[]): PropertyDecorator; /** * JoinColumn decorator used on one-to-one relations to specify owner side of relationship. * It also can be used on both one-to-one and many-to-one relations to specify custom column name * or custom referenced column. */ -export function JoinColumn(optionsOrOptionsArray?: JoinColumnOptions|JoinColumnOptions[]): Function { +export function JoinColumn(optionsOrOptionsArray?: JoinColumnOptions|JoinColumnOptions[]): PropertyDecorator { return function (object: Object, propertyName: string) { const options = Array.isArray(optionsOrOptionsArray) ? optionsOrOptionsArray : [optionsOrOptionsArray || {}]; options.forEach(options => { diff --git a/src/decorator/relations/JoinTable.ts b/src/decorator/relations/JoinTable.ts index ed7ddab587..c9d95b0909 100644 --- a/src/decorator/relations/JoinTable.ts +++ b/src/decorator/relations/JoinTable.ts @@ -6,25 +6,25 @@ import {JoinTableMultipleColumnsOptions} from "../options/JoinTableMultipleColum * JoinTable decorator is used in many-to-many relationship to specify owner side of relationship. * Its also used to set a custom junction table's name, column names and referenced columns. */ -export function JoinTable(): Function; +export function JoinTable(): PropertyDecorator; /** * JoinTable decorator is used in many-to-many relationship to specify owner side of relationship. * Its also used to set a custom junction table's name, column names and referenced columns. */ -export function JoinTable(options: JoinTableOptions): Function; +export function JoinTable(options: JoinTableOptions): PropertyDecorator; /** * JoinTable decorator is used in many-to-many relationship to specify owner side of relationship. * Its also used to set a custom junction table's name, column names and referenced columns. */ -export function JoinTable(options: JoinTableMultipleColumnsOptions): Function; +export function JoinTable(options: JoinTableMultipleColumnsOptions): PropertyDecorator; /** * JoinTable decorator is used in many-to-many relationship to specify owner side of relationship. * Its also used to set a custom junction table's name, column names and referenced columns. */ -export function JoinTable(options?: JoinTableOptions|JoinTableMultipleColumnsOptions): Function { +export function JoinTable(options?: JoinTableOptions|JoinTableMultipleColumnsOptions): PropertyDecorator { return function (object: Object, propertyName: string) { options = options || {} as JoinTableOptions|JoinTableMultipleColumnsOptions; getMetadataArgsStorage().joinTables.push({ diff --git a/src/decorator/relations/ManyToMany.ts b/src/decorator/relations/ManyToMany.ts index f287b434f5..e07a124f04 100644 --- a/src/decorator/relations/ManyToMany.ts +++ b/src/decorator/relations/ManyToMany.ts @@ -7,7 +7,7 @@ import {RelationMetadataArgs} from "../../metadata-args/RelationMetadataArgs"; * entity1 and entity2 ids. This is owner side of the relationship. */ export function ManyToMany(typeFunctionOrTarget: string|((type?: any) => ObjectType), - options?: RelationOptions): Function; + options?: RelationOptions): PropertyDecorator; /** * Many-to-many is a type of relationship when Entity1 can have multiple instances of Entity2, and Entity2 can have @@ -16,7 +16,7 @@ export function ManyToMany(typeFunctionOrTarget: string|((type?: any) => Obje */ export function ManyToMany(typeFunctionOrTarget: string|((type?: any) => ObjectType), inverseSide?: string|((object: T) => any), - options?: RelationOptions): Function; + options?: RelationOptions): PropertyDecorator; /** * Many-to-many is a type of relationship when Entity1 can have multiple instances of Entity2, and Entity2 can have @@ -25,7 +25,7 @@ export function ManyToMany(typeFunctionOrTarget: string|((type?: any) => Obje */ export function ManyToMany(typeFunctionOrTarget: string|((type?: any) => ObjectType), inverseSideOrOptions?: string|((object: T) => any)|RelationOptions, - options?: RelationOptions): Function { + options?: RelationOptions): PropertyDecorator { // normalize parameters let inverseSideProperty: string|((object: T) => any); diff --git a/src/decorator/relations/ManyToOne.ts b/src/decorator/relations/ManyToOne.ts index 7c0031e6c0..0c60ba0bf6 100644 --- a/src/decorator/relations/ManyToOne.ts +++ b/src/decorator/relations/ManyToOne.ts @@ -6,7 +6,7 @@ import {RelationMetadataArgs} from "../../metadata-args/RelationMetadataArgs"; * Entity2 can have a multiple instances of Entity1. Entity1 is an owner of the relationship, and storages Entity2 id * on its own side. */ -export function ManyToOne(typeFunctionOrTarget: string|((type?: any) => ObjectType), options?: RelationOptions): Function; +export function ManyToOne(typeFunctionOrTarget: string|((type?: any) => ObjectType), options?: RelationOptions): PropertyDecorator; /** * Many-to-one relation allows to create type of relation when Entity1 can have single instance of Entity2, but @@ -15,7 +15,7 @@ export function ManyToOne(typeFunctionOrTarget: string|((type?: any) => Objec */ export function ManyToOne(typeFunctionOrTarget: string|((type?: any) => ObjectType), inverseSide?: string|((object: T) => any), - options?: RelationOptions): Function; + options?: RelationOptions): PropertyDecorator; /** * Many-to-one relation allows to create type of relation when Entity1 can have single instance of Entity2, but @@ -24,7 +24,7 @@ export function ManyToOne(typeFunctionOrTarget: string|((type?: any) => Objec */ export function ManyToOne(typeFunctionOrTarget: string|((type?: any) => ObjectType), inverseSideOrOptions?: string|((object: T) => any)|RelationOptions, - options?: RelationOptions): Function { + options?: RelationOptions): PropertyDecorator { // normalize parameters let inverseSideProperty: string|((object: T) => any); diff --git a/src/decorator/relations/OneToMany.ts b/src/decorator/relations/OneToMany.ts index 80e1f7175c..e174ba8f08 100644 --- a/src/decorator/relations/OneToMany.ts +++ b/src/decorator/relations/OneToMany.ts @@ -2,10 +2,10 @@ import {getMetadataArgsStorage, ObjectType, RelationOptions} from "../../"; import {RelationMetadataArgs} from "../../metadata-args/RelationMetadataArgs"; /** - * One-to-many relation allows to create type of relation when Entity2 can have multiple instances of Entity1. - * Entity1 have only one Entity2. Entity1 is an owner of the relationship, and storages Entity2 id on its own side. + * One-to-many relation allows to create type of relation when Entity1 can have multiple instances of Entity2. + * Entity2 have only one Entity1. Entity2 is an owner of the relationship, and storages Entity1 id on its own side. */ -export function OneToMany(typeFunctionOrTarget: string|((type?: any) => ObjectType), inverseSide: string|((object: T) => any), options?: RelationOptions): Function { +export function OneToMany(typeFunctionOrTarget: string|((type?: any) => ObjectType), inverseSide: string|((object: T) => any), options?: RelationOptions): PropertyDecorator { return function (object: Object, propertyName: string) { if (!options) options = {} as RelationOptions; diff --git a/src/decorator/relations/OneToOne.ts b/src/decorator/relations/OneToOne.ts index 85f196b227..e1d8c04982 100644 --- a/src/decorator/relations/OneToOne.ts +++ b/src/decorator/relations/OneToOne.ts @@ -6,7 +6,7 @@ import {RelationMetadataArgs} from "../../metadata-args/RelationMetadataArgs"; * Entity1 is an owner of the relationship, and storages Entity1 id on its own side. */ export function OneToOne(typeFunctionOrTarget: string|((type?: any) => ObjectType), - options?: RelationOptions): Function; + options?: RelationOptions): PropertyDecorator; /** * One-to-one relation allows to create direct relation between two entities. Entity1 have only one Entity2. @@ -14,7 +14,7 @@ export function OneToOne(typeFunctionOrTarget: string|((type?: any) => Object */ export function OneToOne(typeFunctionOrTarget: string|((type?: any) => ObjectType), inverseSide?: string|((object: T) => any), - options?: RelationOptions): Function; + options?: RelationOptions): PropertyDecorator; /** * One-to-one relation allows to create direct relation between two entities. Entity1 have only one Entity2. @@ -22,7 +22,7 @@ export function OneToOne(typeFunctionOrTarget: string|((type?: any) => Object */ export function OneToOne(typeFunctionOrTarget: string|((type?: any) => ObjectType), inverseSideOrOptions?: string|((object: T) => any)|RelationOptions, - options?: RelationOptions): Function { + options?: RelationOptions): PropertyDecorator { // normalize parameters let inverseSideProperty: string|((object: T) => any); diff --git a/src/decorator/relations/RelationCount.ts b/src/decorator/relations/RelationCount.ts index abfb76c2e4..9670c5c895 100644 --- a/src/decorator/relations/RelationCount.ts +++ b/src/decorator/relations/RelationCount.ts @@ -6,7 +6,7 @@ import {RelationCountMetadataArgs} from "../../metadata-args/RelationCountMetada * * @deprecated Do not use this decorator, it may be removed in the future versions */ -export function RelationCount(relation: string|((object: T) => any), alias?: string, queryBuilderFactory?: (qb: SelectQueryBuilder) => SelectQueryBuilder): Function { +export function RelationCount(relation: string|((object: T) => any), alias?: string, queryBuilderFactory?: (qb: SelectQueryBuilder) => SelectQueryBuilder): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().relationCounts.push({ diff --git a/src/decorator/relations/RelationId.ts b/src/decorator/relations/RelationId.ts index c7880e17a6..78855aeb4f 100644 --- a/src/decorator/relations/RelationId.ts +++ b/src/decorator/relations/RelationId.ts @@ -6,7 +6,7 @@ import {RelationIdMetadataArgs} from "../../metadata-args/RelationIdMetadataArgs * * @experimental */ -export function RelationId(relation: string|((object: T) => any), alias?: string, queryBuilderFactory?: (qb: SelectQueryBuilder) => SelectQueryBuilder): Function { +export function RelationId(relation: string|((object: T) => any), alias?: string, queryBuilderFactory?: (qb: SelectQueryBuilder) => SelectQueryBuilder): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().relationIds.push({ diff --git a/src/decorator/tree/Tree.ts b/src/decorator/tree/Tree.ts index e93ab0be9c..79da2fc96b 100644 --- a/src/decorator/tree/Tree.ts +++ b/src/decorator/tree/Tree.ts @@ -8,7 +8,7 @@ import {TreeType} from "../../metadata/types/TreeTypes"; * @TreeParent decorator must be used in tree entities. * TreeRepository can be used to manipulate with tree entities. */ -export function Tree(type: TreeType): Function { +export function Tree(type: TreeType): ClassDecorator { return function (target: Function) { getMetadataArgsStorage().trees.push({ diff --git a/src/decorator/tree/TreeChildren.ts b/src/decorator/tree/TreeChildren.ts index 70de9e5995..2ef0935e0a 100644 --- a/src/decorator/tree/TreeChildren.ts +++ b/src/decorator/tree/TreeChildren.ts @@ -5,7 +5,7 @@ import {RelationMetadataArgs} from "../../metadata-args/RelationMetadataArgs"; * Marks a entity property as a children of the tree. * "Tree children" will contain all children (bind) of this entity. */ -export function TreeChildren(options?: { cascade?: boolean|("insert"|"update"|"remove"|"soft-remove"|"recover")[] }): Function { +export function TreeChildren(options?: { cascade?: boolean|("insert"|"update"|"remove"|"soft-remove"|"recover")[] }): PropertyDecorator { return function (object: Object, propertyName: string) { if (!options) options = {} as RelationOptions; diff --git a/src/decorator/tree/TreeLevelColumn.ts b/src/decorator/tree/TreeLevelColumn.ts index f34a4173ed..24d9b5f2b1 100644 --- a/src/decorator/tree/TreeLevelColumn.ts +++ b/src/decorator/tree/TreeLevelColumn.ts @@ -4,7 +4,7 @@ import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs"; /** * Creates a "level"/"length" column to the table that holds a closure table. */ -export function TreeLevelColumn(): Function { +export function TreeLevelColumn(): PropertyDecorator { return function (object: Object, propertyName: string) { getMetadataArgsStorage().columns.push({ diff --git a/src/decorator/tree/TreeParent.ts b/src/decorator/tree/TreeParent.ts index 4b0d38b9ef..931b78206e 100644 --- a/src/decorator/tree/TreeParent.ts +++ b/src/decorator/tree/TreeParent.ts @@ -5,7 +5,7 @@ import {RelationMetadataArgs} from "../../metadata-args/RelationMetadataArgs"; * Marks a entity property as a parent of the tree. * "Tree parent" indicates who owns (is a parent) of this entity in tree structure. */ -export function TreeParent(): Function { +export function TreeParent(): PropertyDecorator { return function (object: Object, propertyName: string) { // now try to determine it its lazy relation diff --git a/src/driver/Driver.ts b/src/driver/Driver.ts index 1c5f084312..8d683dca9c 100644 --- a/src/driver/Driver.ts +++ b/src/driver/Driver.ts @@ -8,6 +8,7 @@ import {DataTypeDefaults} from "./types/DataTypeDefaults"; import {BaseConnectionOptions} from "../connection/BaseConnectionOptions"; import {TableColumn} from "../schema-builder/table/TableColumn"; import {EntityMetadata} from "../metadata/EntityMetadata"; +import {ReplicationMode} from "./types/ReplicationMode"; /** * Driver organizes TypeORM communication with specific database management system. @@ -102,7 +103,7 @@ export interface Driver { /** * Creates a query runner used for common queries. */ - createQueryRunner(mode: "master"|"slave"): QueryRunner; + createQueryRunner(mode: ReplicationMode): QueryRunner; /** * Replaces parameters in the given sql with special escaping character @@ -175,7 +176,7 @@ export interface Driver { /** * Creates generated map of values generated or returned by database after INSERT query. */ - createGeneratedMap(metadata: EntityMetadata, insertResult: any): ObjectLiteral|undefined; + createGeneratedMap(metadata: EntityMetadata, insertResult: any, entityIndex?: number, entityNum?: number): ObjectLiteral|undefined; /** * Differentiate columns of this table and columns from the given column metadatas columns @@ -193,6 +194,11 @@ export interface Driver { */ isUUIDGenerationSupported(): boolean; + /** + * Returns true if driver supports fulltext indices. + */ + isFullTextColumnTypeSupported(): boolean; + /** * Creates an escaped parameter. */ diff --git a/src/driver/DriverFactory.ts b/src/driver/DriverFactory.ts index f6aa97b017..e3eed40e59 100644 --- a/src/driver/DriverFactory.ts +++ b/src/driver/DriverFactory.ts @@ -9,12 +9,13 @@ import {ReactNativeDriver} from "./react-native/ReactNativeDriver"; import {NativescriptDriver} from "./nativescript/NativescriptDriver"; import {SqljsDriver} from "./sqljs/SqljsDriver"; import {MysqlDriver} from "./mysql/MysqlDriver"; -import {PostgresDriver} from "./postgres/PostgresDriver"; +import {PostgresDriver, AuroraDataApiPostgresDriver} from "./postgres/PostgresDriver"; import {ExpoDriver} from "./expo/ExpoDriver"; import {AuroraDataApiDriver} from "./aurora-data-api/AuroraDataApiDriver"; import {Driver} from "./Driver"; import {Connection} from "../connection/Connection"; import {SapDriver} from "./sap/SapDriver"; +import {BetterSqlite3Driver} from "./better-sqlite3/BetterSqlite3Driver"; /** * Helps to create drivers. @@ -39,6 +40,8 @@ export class DriverFactory { return new MysqlDriver(connection); case "sqlite": return new SqliteDriver(connection); + case "better-sqlite3": + return new BetterSqlite3Driver(connection); case "cordova": return new CordovaDriver(connection); case "nativescript": @@ -57,6 +60,8 @@ export class DriverFactory { return new ExpoDriver(connection); case "aurora-data-api": return new AuroraDataApiDriver(connection); + case "aurora-data-api-pg": + return new AuroraDataApiPostgresDriver(connection); default: throw new MissingDriverError(type); } diff --git a/src/driver/DriverUtils.ts b/src/driver/DriverUtils.ts index 36d80ff07f..56d7309d9f 100644 --- a/src/driver/DriverUtils.ts +++ b/src/driver/DriverUtils.ts @@ -28,7 +28,7 @@ export class DriverUtils { if (buildOptions && buildOptions.useSid) { urlDriverOptions.sid = parsedUrl.database; } - return Object.assign({}, options, urlDriverOptions); + return Object.assign({}, urlDriverOptions, options); } return Object.assign({}, options); } @@ -68,7 +68,11 @@ export class DriverUtils { const preBase = url.substr(firstSlashes + 2); const secondSlash = preBase.indexOf("/"); const base = (secondSlash !== -1) ? preBase.substr(0, secondSlash) : preBase; - const afterBase = (secondSlash !== -1) ? preBase.substr(secondSlash + 1) : undefined; + let afterBase = (secondSlash !== -1) ? preBase.substr(secondSlash + 1) : undefined; + // remove mongodb query params + if (afterBase && afterBase.indexOf("?") !== -1) { + afterBase = afterBase.substr(0, afterBase.indexOf("?")); + } const lastAtSign = base.lastIndexOf("@"); const usernameAndPassword = base.substr(0, lastAtSign); diff --git a/src/driver/aurora-data-api-pg/AuroraDataApiPostgresConnectionOptions.ts b/src/driver/aurora-data-api-pg/AuroraDataApiPostgresConnectionOptions.ts new file mode 100644 index 0000000000..18078aed82 --- /dev/null +++ b/src/driver/aurora-data-api-pg/AuroraDataApiPostgresConnectionOptions.ts @@ -0,0 +1,38 @@ +import {BaseConnectionOptions} from "../../connection/BaseConnectionOptions"; + +/** + * Postgres-specific connection options. + */ +export interface AuroraDataApiPostgresConnectionOptions extends BaseConnectionOptions { + + /** + * Database type. + */ + readonly type: "aurora-data-api-pg"; + + readonly region: string; + + readonly secretArn: string; + + readonly resourceArn: string; + + readonly database: string; + + /** + * The Postgres extension to use to generate UUID columns. Defaults to uuid-ossp. + * If pgcrypto is selected, TypeORM will use the gen_random_uuid() function from this extension. + * If uuid-ossp is selected, TypeORM will use the uuid_generate_v4() function from this extension. + */ + readonly uuidExtension?: "pgcrypto" | "uuid-ossp"; + + + /* + * Function handling errors thrown by drivers pool. + * Defaults to logging error with `warn` level. + */ + readonly poolErrorHandler?: (err: any) => any; + + readonly serviceConfigOptions?: { [key: string]: any }; + + readonly formatOptions?: { [key: string]: any }; +} diff --git a/src/driver/aurora-data-api-pg/AuroraDataApiPostgresQueryRunner.ts b/src/driver/aurora-data-api-pg/AuroraDataApiPostgresQueryRunner.ts new file mode 100644 index 0000000000..f9ec0cb06d --- /dev/null +++ b/src/driver/aurora-data-api-pg/AuroraDataApiPostgresQueryRunner.ts @@ -0,0 +1,139 @@ +import {QueryRunnerAlreadyReleasedError} from "../../error/QueryRunnerAlreadyReleasedError"; +import {TransactionAlreadyStartedError} from "../../error/TransactionAlreadyStartedError"; +import {TransactionNotStartedError} from "../../error/TransactionNotStartedError"; +import {QueryRunner} from "../../query-runner/QueryRunner"; +import {IsolationLevel} from "../types/IsolationLevel"; +import {AuroraDataApiPostgresDriver} from "../postgres/PostgresDriver"; +import {PostgresQueryRunner} from "../postgres/PostgresQueryRunner"; +import {ReplicationMode} from "../types/ReplicationMode"; + +class PostgresQueryRunnerWrapper extends PostgresQueryRunner { + driver: any; + + constructor(driver: any, mode: ReplicationMode) { + super(driver, mode); + } +} + +/** + * Runs queries on a single postgres database connection. + */ +export class AuroraDataApiPostgresQueryRunner extends PostgresQueryRunnerWrapper implements QueryRunner { + + // ------------------------------------------------------------------------- + // Public Implemented Properties + // ------------------------------------------------------------------------- + + /** + * Database driver used by connection. + */ + driver: AuroraDataApiPostgresDriver; + + // ------------------------------------------------------------------------- + // Protected Properties + // ------------------------------------------------------------------------- + + /** + * Promise used to obtain a database connection for a first time. + */ + protected databaseConnectionPromise: Promise; + + /** + * Special callback provided by a driver used to release a created connection. + */ + protected releaseCallback: Function; + + // ------------------------------------------------------------------------- + // Constructor + // ------------------------------------------------------------------------- + + constructor(driver: AuroraDataApiPostgresDriver, mode: ReplicationMode) { + super(driver, mode); + } + + // ------------------------------------------------------------------------- + // Public Methods + // ------------------------------------------------------------------------- + + /** + * Creates/uses database connection from the connection pool to perform further operations. + * Returns obtained database connection. + */ + connect(): Promise { + if (this.databaseConnection) + return Promise.resolve(this.databaseConnection); + + if (this.databaseConnectionPromise) + return this.databaseConnectionPromise; + + if (this.mode === "slave" && this.driver.isReplicated) { + this.databaseConnectionPromise = this.driver.obtainSlaveConnection().then(([ connection, release]: any[]) => { + this.driver.connectedQueryRunners.push(this); + this.databaseConnection = connection; + this.releaseCallback = release; + return this.databaseConnection; + }); + + } else { // master + this.databaseConnectionPromise = this.driver.obtainMasterConnection().then(([connection, release]: any[]) => { + this.driver.connectedQueryRunners.push(this); + this.databaseConnection = connection; + this.releaseCallback = release; + return this.databaseConnection; + }); + } + + return this.databaseConnectionPromise; + } + + /** + * Starts transaction on the current connection. + */ + async startTransaction(isolationLevel?: IsolationLevel): Promise { + if (this.isTransactionActive) + throw new TransactionAlreadyStartedError(); + + this.isTransactionActive = true; + await this.driver.client.startTransaction(); + } + + /** + * Commits transaction. + * Error will be thrown if transaction was not started. + */ + async commitTransaction(): Promise { + if (!this.isTransactionActive) + throw new TransactionNotStartedError(); + + await this.driver.client.commitTransaction(); + this.isTransactionActive = false; + } + + /** + * Rollbacks transaction. + * Error will be thrown if transaction was not started. + */ + async rollbackTransaction(): Promise { + if (!this.isTransactionActive) + throw new TransactionNotStartedError(); + + await this.driver.client.rollbackTransaction(); + this.isTransactionActive = false; + } + + /** + * Executes a given SQL query. + */ + async query(query: string, parameters?: any[]): Promise { + if (this.isReleased) + throw new QueryRunnerAlreadyReleasedError(); + + const result = await this.driver.client.query(query, parameters); + + if (result.records) { + return result.records; + } + + return result; + } +} diff --git a/src/driver/aurora-data-api/AuroraDataApiConnection.ts b/src/driver/aurora-data-api/AuroraDataApiConnection.ts index 386248809f..e79bc30dc9 100644 --- a/src/driver/aurora-data-api/AuroraDataApiConnection.ts +++ b/src/driver/aurora-data-api/AuroraDataApiConnection.ts @@ -1,6 +1,7 @@ import {AuroraDataApiQueryRunner} from "./AuroraDataApiQueryRunner"; import {Connection} from "../../connection/Connection"; import {ConnectionOptions, QueryRunner} from "../.."; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with MySQL DBMS. @@ -13,7 +14,7 @@ export class AuroraDataApiConnection extends Connection { this.queryRunnter = queryRunner; } - public createQueryRunner(mode: "master" | "slave" = "master"): QueryRunner { + public createQueryRunner(mode: ReplicationMode): QueryRunner { return this.queryRunnter; } diff --git a/src/driver/aurora-data-api/AuroraDataApiConnectionOptions.ts b/src/driver/aurora-data-api/AuroraDataApiConnectionOptions.ts index 9e9b0d283e..5e5722c227 100644 --- a/src/driver/aurora-data-api/AuroraDataApiConnectionOptions.ts +++ b/src/driver/aurora-data-api/AuroraDataApiConnectionOptions.ts @@ -21,6 +21,10 @@ export interface AuroraDataApiConnectionOptions extends BaseConnectionOptions, A readonly database: string; + readonly serviceConfigOptions?: { [key: string]: any }; // pass optional AWS.ConfigurationOptions here + + readonly formatOptions?: { [key: string]: any }; + /** * Use spatial functions like GeomFromText and AsText which are removed in MySQL 8. * (Default: true) diff --git a/src/driver/aurora-data-api/AuroraDataApiDriver.ts b/src/driver/aurora-data-api/AuroraDataApiDriver.ts index f120c1bfba..9f6cc71cc9 100644 --- a/src/driver/aurora-data-api/AuroraDataApiDriver.ts +++ b/src/driver/aurora-data-api/AuroraDataApiDriver.ts @@ -16,6 +16,7 @@ import {AuroraDataApiConnectionCredentialsOptions} from "./AuroraDataApiConnecti import {EntityMetadata} from "../../metadata/EntityMetadata"; import {OrmUtils} from "../../util/OrmUtils"; import {ApplyValueTransformers} from "../../util/ApplyValueTransformers"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with MySQL DBMS. @@ -306,6 +307,8 @@ export class AuroraDataApiDriver implements Driver { this.options.resourceArn, this.options.database, (query: string, parameters?: any[]) => this.connection.logger.logQuery(query, parameters), + this.options.serviceConfigOptions, + this.options.formatOptions, ); // validate options to make sure everything is set @@ -353,7 +356,7 @@ export class AuroraDataApiDriver implements Driver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master") { + createQueryRunner(mode: ReplicationMode) { return new AuroraDataApiQueryRunner(this); } @@ -748,6 +751,13 @@ export class AuroraDataApiDriver implements Driver { return false; } + /** + * Returns true if driver supports fulltext indices. + */ + isFullTextColumnTypeSupported(): boolean { + return true; + } + /** * Creates an escaped parameter. */ diff --git a/src/driver/aurora-data-api/AuroraDataApiQueryRunner.ts b/src/driver/aurora-data-api/AuroraDataApiQueryRunner.ts index 3d5e69069b..fcc8a51ab6 100644 --- a/src/driver/aurora-data-api/AuroraDataApiQueryRunner.ts +++ b/src/driver/aurora-data-api/AuroraDataApiQueryRunner.ts @@ -17,7 +17,7 @@ import {TableIndexOptions} from "../../schema-builder/options/TableIndexOptions" import {TableUnique} from "../../schema-builder/table/TableUnique"; import {BaseQueryRunner} from "../../query-runner/BaseQueryRunner"; import {Broadcaster} from "../../subscriber/Broadcaster"; -import {ColumnType, PromiseUtils} from "../../index"; +import {ColumnType} from "../../index"; import {TableCheck} from "../../schema-builder/table/TableCheck"; import {IsolationLevel} from "../types/IsolationLevel"; import {TableExclusion} from "../../schema-builder/table/TableExclusion"; @@ -470,7 +470,9 @@ export class AuroraDataApiQueryRunner extends BaseQueryRunner implements QueryRu * Creates a new columns from the column in the table. */ async addColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.addColumn(tableOrName, column)); + for (const column of columns) { + await this.addColumn(tableOrName, column); + } } /** @@ -683,7 +685,9 @@ export class AuroraDataApiQueryRunner extends BaseQueryRunner implements QueryRu * Changes a column in the table. */ async changeColumns(tableOrName: Table|string, changedColumns: { newColumn: TableColumn, oldColumn: TableColumn }[]): Promise { - await PromiseUtils.runInSequence(changedColumns, changedColumn => this.changeColumn(tableOrName, changedColumn.oldColumn, changedColumn.newColumn)); + for (const {oldColumn, newColumn} of changedColumns) { + await this.changeColumn(tableOrName, oldColumn, newColumn) + } } /** @@ -775,7 +779,9 @@ export class AuroraDataApiQueryRunner extends BaseQueryRunner implements QueryRu * Drops the columns in the table. */ async dropColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.dropColumn(tableOrName, column)); + for (const column of columns) { + await this.dropColumn(tableOrName, column); + } } /** @@ -1624,4 +1630,26 @@ export class AuroraDataApiQueryRunner extends BaseQueryRunner implements QueryRu return c; } + /** + * Checks if column display width is by default. + */ + protected isDefaultColumnWidth(table: Table, column: TableColumn, width: number): boolean { + // if table have metadata, we check if length is specified in column metadata + if (this.connection.hasMetadata(table.name)) { + const metadata = this.connection.getMetadata(table.name); + const columnMetadata = metadata.findColumnWithDatabaseName(column.name); + if (columnMetadata && columnMetadata.width) + return false; + } + + const defaultWidthForType = this.connection.driver.dataTypeDefaults + && this.connection.driver.dataTypeDefaults[column.type] + && this.connection.driver.dataTypeDefaults[column.type].width; + + if (defaultWidthForType) { + return defaultWidthForType === width; + } + return false; + } + } diff --git a/src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts b/src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts new file mode 100644 index 0000000000..09422cbfc0 --- /dev/null +++ b/src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts @@ -0,0 +1,60 @@ +import {BaseConnectionOptions} from "../../connection/BaseConnectionOptions"; + +/** + * Sqlite-specific connection options. + */ +export interface BetterSqlite3ConnectionOptions extends BaseConnectionOptions { + + /** + * Database type. + */ + readonly type: "better-sqlite3"; + + /** + * Storage type or path to the storage. + */ + readonly database: string; + + /** + * Encryption key for for SQLCipher. + */ + readonly key?: string; + + /** + * Cache size of sqlite statement to speed up queries. + * Default: 100. + */ + readonly statementCacheSize?: number; + + /** + * Function to run before a database is used in typeorm. + * You can set pragmas, register plugins or register + * functions or aggregates in this function. + */ + readonly prepareDatabase?: (db: any) => void | Promise; + + /** + * Open the database connection in readonly mode. + * Default: false. + */ + readonly readonly?: boolean; + + /** + * If the database does not exist, an Error will be thrown instead of creating a new file. + * This option does not affect in-memory or readonly database connections. + * Default: false. + */ + readonly fileMustExist?: boolean; + + /** + * The number of milliseconds to wait when executing queries + * on a locked database, before throwing a SQLITE_BUSY error. + * Default: 5000. + */ + readonly timeout?: number; + + /** + * Provide a function that gets called with every SQL string executed by the database connection. + */ + readonly verbose?: Function; +} \ No newline at end of file diff --git a/src/driver/better-sqlite3/BetterSqlite3Driver.ts b/src/driver/better-sqlite3/BetterSqlite3Driver.ts new file mode 100644 index 0000000000..25c9c2f3bc --- /dev/null +++ b/src/driver/better-sqlite3/BetterSqlite3Driver.ts @@ -0,0 +1,142 @@ +import mkdirp from 'mkdirp'; +import path from 'path'; +import { DriverPackageNotInstalledError } from "../../error/DriverPackageNotInstalledError"; +import { DriverOptionNotSetError } from "../../error/DriverOptionNotSetError"; +import { PlatformTools } from "../../platform/PlatformTools"; +import { Connection } from "../../connection/Connection"; +import { ColumnType } from "../types/ColumnTypes"; +import { QueryRunner } from "../../query-runner/QueryRunner"; +import { AbstractSqliteDriver } from "../sqlite-abstract/AbstractSqliteDriver"; +import { BetterSqlite3ConnectionOptions } from "./BetterSqlite3ConnectionOptions"; +import { BetterSqlite3QueryRunner } from "./BetterSqlite3QueryRunner"; +import {ReplicationMode} from "../types/ReplicationMode"; + +/** + * Organizes communication with sqlite DBMS. + */ +export class BetterSqlite3Driver extends AbstractSqliteDriver { + + // ------------------------------------------------------------------------- + // Public Implemented Properties + // ------------------------------------------------------------------------- + + /** + * Connection options. + */ + options: BetterSqlite3ConnectionOptions; + + /** + * SQLite underlying library. + */ + sqlite: any; + + // ------------------------------------------------------------------------- + // Constructor + // ------------------------------------------------------------------------- + + constructor(connection: Connection) { + super(connection); + + this.connection = connection; + this.options = connection.options as BetterSqlite3ConnectionOptions; + this.database = this.options.database; + + // validate options to make sure everything is set + if (!this.options.database) + throw new DriverOptionNotSetError("database"); + + // load sqlite package + this.loadDependencies(); + } + + // ------------------------------------------------------------------------- + // Public Methods + // ------------------------------------------------------------------------- + + /** + * Closes connection with database. + */ + async disconnect(): Promise { + this.queryRunner = undefined; + this.databaseConnection.close(); + } + + /** + * Creates a query runner used to execute database queries. + */ + createQueryRunner(mode: ReplicationMode): QueryRunner { + if (!this.queryRunner) + this.queryRunner = new BetterSqlite3QueryRunner(this); + + return this.queryRunner; + } + + normalizeType(column: { type?: ColumnType, length?: number | string, precision?: number, scale?: number }): string { + if ((column.type as any) === Buffer) { + return "blob"; + } + + return super.normalizeType(column); + } + + // ------------------------------------------------------------------------- + // Protected Methods + // ------------------------------------------------------------------------- + + /** + * Creates connection with the database. + */ + protected async createDatabaseConnection() { + // not to create database directory if is in memory + if (this.options.database !== ":memory:") + await this.createDatabaseDirectory(this.options.database); + + const { + database, + readonly = false, + fileMustExist = false, + timeout = 5000, + verbose = null, + prepareDatabase + } = this.options; + const databaseConnection = this.sqlite(database, { readonly, fileMustExist, timeout, verbose }); + + // we need to enable foreign keys in sqlite to make sure all foreign key related features + // working properly. this also makes onDelete to work with sqlite. + databaseConnection.exec(`PRAGMA foreign_keys = ON`); + + // turn on WAL mode to enhance performance + databaseConnection.exec(`PRAGMA journal_mode = WAL`); + + // in the options, if encryption key for SQLCipher is setted. + if (this.options.key) { + databaseConnection.exec(`PRAGMA key = ${JSON.stringify(this.options.key)}`); + } + + if (typeof prepareDatabase === "function") { + prepareDatabase(databaseConnection); + } + + return databaseConnection; + } + + /** + * If driver dependency is not given explicitly, then try to load it via "require". + */ + protected loadDependencies(): void { + try { + this.sqlite = PlatformTools.load("better-sqlite3"); + + } catch (e) { + throw new DriverPackageNotInstalledError("SQLite", "better-sqlite3"); + } + } + + /** + * Auto creates database directory if it does not exist. + */ + protected async createDatabaseDirectory(fullPath: string): Promise { + await mkdirp(path.dirname(fullPath)); + } + +} diff --git a/src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts b/src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts new file mode 100644 index 0000000000..7df796ade4 --- /dev/null +++ b/src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts @@ -0,0 +1,106 @@ +import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError"; +import { QueryFailedError } from "../../error/QueryFailedError"; +import { AbstractSqliteQueryRunner } from "../sqlite-abstract/AbstractSqliteQueryRunner"; +import { Broadcaster } from "../../subscriber/Broadcaster"; +import { BetterSqlite3Driver } from "./BetterSqlite3Driver"; + +/** + * Runs queries on a single sqlite database connection. + * + * Does not support compose primary keys with autoincrement field. + * todo: need to throw exception for this case. + */ +export class BetterSqlite3QueryRunner extends AbstractSqliteQueryRunner { + + /** + * Database driver used by connection. + */ + driver: BetterSqlite3Driver; + + // ------------------------------------------------------------------------- + // Constructor + // ------------------------------------------------------------------------- + + constructor(driver: BetterSqlite3Driver) { + super(); + this.driver = driver; + this.connection = driver.connection; + this.broadcaster = new Broadcaster(this); + if (typeof this.driver.options.statementCacheSize === "number") { + this.cacheSize = this.driver.options.statementCacheSize; + } else { + this.cacheSize = 100; + } + } + + private cacheSize: number; + private stmtCache = new Map(); + + private async getStmt(query: string) { + if (this.cacheSize > 0) { + let stmt = this.stmtCache.get(query); + if (!stmt) { + const databaseConnection = await this.connect(); + stmt = databaseConnection.prepare(query); + this.stmtCache.set(query, stmt); + while (this.stmtCache.size > this.cacheSize) { + // since es6 map keeps the insertion order, + // it comes to be FIFO cache + const key = this.stmtCache.keys().next().value; + this.stmtCache.delete(key); + } + } + return stmt; + } else { + const databaseConnection = await this.connect(); + return databaseConnection.prepare(query); + } + } + + /** + * Executes a given SQL query. + */ + async query(query: string, parameters?: any[]): Promise { + if (this.isReleased) + throw new QueryRunnerAlreadyReleasedError(); + + const connection = this.driver.connection; + + parameters = parameters || []; + for (let i = 0; i < parameters.length; i++) { + // in "where" clauses the parameters are not escaped by the driver + if (typeof parameters[i] === "boolean") + parameters[i] = +parameters[i]; + } + + this.driver.connection.logger.logQuery(query, parameters, this); + const queryStartTime = +new Date(); + + const stmt = await this.getStmt(query); + + try { + + let result: any; + if (stmt.reader) { + result = stmt.all.apply(stmt, parameters); + } else { + result = stmt.run.apply(stmt, parameters); + if (query.substr(0, 6) === "INSERT") { + result = result.lastInsertRowid; + } + } + + // log slow queries if maxQueryExecution time is set + const maxQueryExecutionTime = connection.options.maxQueryExecutionTime; + const queryEndTime = +new Date(); + const queryExecutionTime = queryEndTime - queryStartTime; + if (maxQueryExecutionTime && queryExecutionTime > maxQueryExecutionTime) + connection.logger.logQuerySlow(queryExecutionTime, query, parameters, this); + + return result; + } catch (err) { + connection.logger.logQueryError(err, query, parameters, this); + throw new QueryFailedError(query, parameters, err); + } + } +} \ No newline at end of file diff --git a/src/driver/cockroachdb/CockroachDriver.ts b/src/driver/cockroachdb/CockroachDriver.ts index c150d5443b..2b90e6a589 100644 --- a/src/driver/cockroachdb/CockroachDriver.ts +++ b/src/driver/cockroachdb/CockroachDriver.ts @@ -19,6 +19,7 @@ import {EntityMetadata} from "../../metadata/EntityMetadata"; import {OrmUtils} from "../../util/OrmUtils"; import {CockroachQueryRunner} from "./CockroachQueryRunner"; import {ApplyValueTransformers} from "../../util/ApplyValueTransformers"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with Cockroach DBMS. @@ -284,7 +285,7 @@ export class CockroachDriver implements Driver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master") { + createQueryRunner(mode: ReplicationMode) { return new CockroachQueryRunner(this, mode); } @@ -651,6 +652,13 @@ export class CockroachDriver implements Driver { return true; } + /** + * Returns true if driver supports fulltext indices. + */ + isFullTextColumnTypeSupported(): boolean { + return false; + } + /** * Creates an escaped parameter. */ diff --git a/src/driver/cockroachdb/CockroachQueryRunner.ts b/src/driver/cockroachdb/CockroachQueryRunner.ts index 5297a78443..4675c495d9 100644 --- a/src/driver/cockroachdb/CockroachQueryRunner.ts +++ b/src/driver/cockroachdb/CockroachQueryRunner.ts @@ -18,11 +18,11 @@ import {TableIndexOptions} from "../../schema-builder/options/TableIndexOptions" import {TableUnique} from "../../schema-builder/table/TableUnique"; import {BaseQueryRunner} from "../../query-runner/BaseQueryRunner"; import {OrmUtils} from "../../util/OrmUtils"; -import {PromiseUtils} from "../../"; import {TableCheck} from "../../schema-builder/table/TableCheck"; import {ColumnType} from "../../index"; import {IsolationLevel} from "../types/IsolationLevel"; import {TableExclusion} from "../../schema-builder/table/TableExclusion"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Runs queries on a single postgres database connection. @@ -66,7 +66,7 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner // Constructor // ------------------------------------------------------------------------- - constructor(driver: CockroachDriver, mode: "master"|"slave" = "master") { + constructor(driver: CockroachDriver, mode: ReplicationMode) { super(); this.driver = driver; this.connection = driver.connection; @@ -159,7 +159,9 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner } catch (e) { if (e.code === "40001") { await this.query("ROLLBACK TO SAVEPOINT cockroach_restart"); - await PromiseUtils.runInSequence(this.queries, q => this.query(q.query, q.parameters)); + for (const q of this.queries) { + await this.query(q.query, q.parameters); + } await this.commitTransaction(); } } @@ -594,7 +596,9 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner * Creates a new columns from the column in the table. */ async addColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.addColumn(tableOrName, column)); + for (const column of columns) { + await this.addColumn(tableOrName, column); + } } /** @@ -844,7 +848,9 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner * Changes a column in the table. */ async changeColumns(tableOrName: Table|string, changedColumns: { newColumn: TableColumn, oldColumn: TableColumn }[]): Promise { - await PromiseUtils.runInSequence(changedColumns, changedColumn => this.changeColumn(tableOrName, changedColumn.oldColumn, changedColumn.newColumn)); + for (const {oldColumn, newColumn} of changedColumns) { + await this.changeColumn(tableOrName, oldColumn, newColumn); + } } /** @@ -923,7 +929,9 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner * Drops the columns in the table. */ async dropColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.dropColumn(tableOrName, column)); + for (const column of columns) { + await this.dropColumn(tableOrName, column); + } } /** @@ -1014,7 +1022,9 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner * Creates new unique constraints. */ async createUniqueConstraints(tableOrName: Table|string, uniqueConstraints: TableUnique[]): Promise { - await PromiseUtils.runInSequence(uniqueConstraints, uniqueConstraint => this.createUniqueConstraint(tableOrName, uniqueConstraint)); + for (const uniqueConstraint of uniqueConstraints) { + await this.createUniqueConstraint(tableOrName, uniqueConstraint); + } } /** @@ -1038,7 +1048,9 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner * Drops unique constraints. */ async dropUniqueConstraints(tableOrName: Table|string, uniqueConstraints: TableUnique[]): Promise { - await PromiseUtils.runInSequence(uniqueConstraints, uniqueConstraint => this.dropUniqueConstraint(tableOrName, uniqueConstraint)); + for (const uniqueConstraint of uniqueConstraints) { + await this.dropUniqueConstraint(tableOrName, uniqueConstraint); + } } /** @@ -1136,7 +1148,9 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner * Creates a new foreign keys. */ async createForeignKeys(tableOrName: Table|string, foreignKeys: TableForeignKey[]): Promise { - await PromiseUtils.runInSequence(foreignKeys, foreignKey => this.createForeignKey(tableOrName, foreignKey)); + for (const foreignKey of foreignKeys) { + await this.createForeignKey(tableOrName, foreignKey); + } } /** @@ -1158,7 +1172,9 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner * Drops a foreign keys from the table. */ async dropForeignKeys(tableOrName: Table|string, foreignKeys: TableForeignKey[]): Promise { - await PromiseUtils.runInSequence(foreignKeys, foreignKey => this.dropForeignKey(tableOrName, foreignKey)); + for (const foreignKey of foreignKeys) { + await this.dropForeignKey(tableOrName, foreignKey); + } } /** @@ -1196,7 +1212,9 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner * Creates a new indices */ async createIndices(tableOrName: Table|string, indices: TableIndex[]): Promise { - await PromiseUtils.runInSequence(indices, index => this.createIndex(tableOrName, index)); + for (const index of indices) { + await this.createIndex(tableOrName, index); + } } /** @@ -1218,7 +1236,9 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner * Drops an indices from the table. */ async dropIndices(tableOrName: Table|string, indices: TableIndex[]): Promise { - await PromiseUtils.runInSequence(indices, index => this.dropIndex(tableOrName, index)); + for (const index of indices) { + await this.dropIndex(tableOrName, index); + } } /** diff --git a/src/driver/cordova/CordovaDriver.ts b/src/driver/cordova/CordovaDriver.ts index bec6b6b63f..6f6eb3a463 100644 --- a/src/driver/cordova/CordovaDriver.ts +++ b/src/driver/cordova/CordovaDriver.ts @@ -5,6 +5,7 @@ import {QueryRunner} from "../../query-runner/QueryRunner"; import {Connection} from "../../connection/Connection"; import {DriverOptionNotSetError} from "../../error/DriverOptionNotSetError"; import {DriverPackageNotInstalledError} from "../../error/DriverPackageNotInstalledError"; +import {ReplicationMode} from "../types/ReplicationMode"; // needed for typescript compiler interface Window { @@ -15,7 +16,7 @@ declare var window: Window; export class CordovaDriver extends AbstractSqliteDriver { options: CordovaConnectionOptions; - + // ------------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------------- @@ -37,7 +38,7 @@ export class CordovaDriver extends AbstractSqliteDriver { // load sqlite package this.loadDependencies(); } - + // ------------------------------------------------------------------------- // Public Methods @@ -52,17 +53,17 @@ export class CordovaDriver extends AbstractSqliteDriver { this.databaseConnection.close(ok, fail); }); } - + /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master"): QueryRunner { + createQueryRunner(mode: ReplicationMode): QueryRunner { if (!this.queryRunner) this.queryRunner = new CordovaQueryRunner(this); return this.queryRunner; } - + // ------------------------------------------------------------------------- // Protected Methods // ------------------------------------------------------------------------- @@ -104,4 +105,4 @@ export class CordovaDriver extends AbstractSqliteDriver { throw new DriverPackageNotInstalledError("Cordova-SQLite", "cordova-sqlite-storage"); } } -} \ No newline at end of file +} diff --git a/src/driver/expo/ExpoDriver.ts b/src/driver/expo/ExpoDriver.ts index fffd8ffff5..1086e42e71 100644 --- a/src/driver/expo/ExpoDriver.ts +++ b/src/driver/expo/ExpoDriver.ts @@ -4,10 +4,11 @@ import {ExpoQueryRunner} from "./ExpoQueryRunner"; import {QueryRunner} from "../../query-runner/QueryRunner"; import {Connection} from "../../connection/Connection"; import {DriverOptionNotSetError} from "../../error/DriverOptionNotSetError"; +import {ReplicationMode} from "../types/ReplicationMode"; export class ExpoDriver extends AbstractSqliteDriver { options: ExpoConnectionOptions; - + // ------------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------------- @@ -20,14 +21,14 @@ export class ExpoDriver extends AbstractSqliteDriver { // validate options to make sure everything is set if (!this.options.database) throw new DriverOptionNotSetError("database"); - + if (!this.options.driver) throw new DriverOptionNotSetError("driver"); // load sqlite package this.sqlite = this.options.driver; } - + // ------------------------------------------------------------------------- // Public Methods @@ -40,6 +41,7 @@ export class ExpoDriver extends AbstractSqliteDriver { return new Promise((ok, fail) => { try { this.queryRunner = undefined; + this.databaseConnection._db.close(); this.databaseConnection = undefined; ok(); } catch (error) { @@ -47,17 +49,17 @@ export class ExpoDriver extends AbstractSqliteDriver { } }); } - + /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master"): QueryRunner { + createQueryRunner(mode: ReplicationMode): QueryRunner { if (!this.queryRunner) this.queryRunner = new ExpoQueryRunner(this); return this.queryRunner; } - + // ------------------------------------------------------------------------- // Protected Methods // ------------------------------------------------------------------------- diff --git a/src/driver/mongodb/MongoDriver.ts b/src/driver/mongodb/MongoDriver.ts index bd45bd3f19..7319415e98 100644 --- a/src/driver/mongodb/MongoDriver.ts +++ b/src/driver/mongodb/MongoDriver.ts @@ -16,6 +16,7 @@ import {ConnectionOptions} from "../../connection/ConnectionOptions"; import {EntityMetadata} from "../../metadata/EntityMetadata"; import {ObjectUtils} from "../../util/ObjectUtils"; import {ApplyValueTransformers} from "../../util/ApplyValueTransformers"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with MongoDB. @@ -262,7 +263,7 @@ export class MongoDriver implements Driver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master") { + createQueryRunner(mode: ReplicationMode) { return this.queryRunner!; } @@ -389,6 +390,13 @@ export class MongoDriver implements Driver { return false; } + /** + * Returns true if driver supports fulltext indices. + */ + isFullTextColumnTypeSupported(): boolean { + return false; + } + /** * Creates an escaped parameter. */ diff --git a/src/driver/mongodb/typings.ts b/src/driver/mongodb/typings.ts index dea33ea258..f060531135 100644 --- a/src/driver/mongodb/typings.ts +++ b/src/driver/mongodb/typings.ts @@ -4271,7 +4271,7 @@ export interface BulkWriteResult { /** * Return an array of upserted ids. */ - getUpsertedIds(): Array; + getUpsertedIds(): Array<{ _id: string, index: number }>; /** * Retrieve the write concern error if any. diff --git a/src/driver/mysql/MysqlDriver.ts b/src/driver/mysql/MysqlDriver.ts index acb357fb2e..5dc18f74af 100644 --- a/src/driver/mysql/MysqlDriver.ts +++ b/src/driver/mysql/MysqlDriver.ts @@ -18,6 +18,7 @@ import {MysqlConnectionCredentialsOptions} from "./MysqlConnectionCredentialsOpt import {EntityMetadata} from "../../metadata/EntityMetadata"; import {OrmUtils} from "../../util/OrmUtils"; import {ApplyValueTransformers} from "../../util/ApplyValueTransformers"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with MySQL DBMS. @@ -385,7 +386,7 @@ export class MysqlDriver implements Driver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master") { + createQueryRunner(mode: ReplicationMode) { return new MysqlQueryRunner(this, mode); } @@ -709,11 +710,13 @@ export class MysqlDriver implements Driver { /** * Creates generated map of values generated or returned by database after INSERT query. */ - createGeneratedMap(metadata: EntityMetadata, insertResult: any) { + createGeneratedMap(metadata: EntityMetadata, insertResult: any, entityIndex: number) { const generatedMap = metadata.generatedColumns.reduce((map, generatedColumn) => { let value: any; if (generatedColumn.generationStrategy === "increment" && insertResult.insertId) { - value = insertResult.insertId; + // NOTE: When multiple rows is inserted by a single INSERT statement, + // `insertId` is the value generated for the first inserted row only. + value = insertResult.insertId + entityIndex; // } else if (generatedColumn.generationStrategy === "uuid") { // console.log("getting db value:", generatedColumn.databaseName); // value = generatedColumn.getEntityValue(uuidMap); @@ -798,6 +801,13 @@ export class MysqlDriver implements Driver { return false; } + /** + * Returns true if driver supports fulltext indices. + */ + isFullTextColumnTypeSupported(): boolean { + return true; + } + /** * Creates an escaped parameter. */ diff --git a/src/driver/mysql/MysqlQueryRunner.ts b/src/driver/mysql/MysqlQueryRunner.ts index 2c6d808200..e390ed5ea3 100644 --- a/src/driver/mysql/MysqlQueryRunner.ts +++ b/src/driver/mysql/MysqlQueryRunner.ts @@ -18,11 +18,12 @@ import {TableIndexOptions} from "../../schema-builder/options/TableIndexOptions" import {TableUnique} from "../../schema-builder/table/TableUnique"; import {BaseQueryRunner} from "../../query-runner/BaseQueryRunner"; import {Broadcaster} from "../../subscriber/Broadcaster"; -import {ColumnType, PromiseUtils} from "../../index"; +import {ColumnType} from "../../index"; import {TableCheck} from "../../schema-builder/table/TableCheck"; import {IsolationLevel} from "../types/IsolationLevel"; import {TableExclusion} from "../../schema-builder/table/TableExclusion"; import {VersionUtils} from "../../util/VersionUtils"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Runs queries on a single mysql database connection. @@ -51,7 +52,7 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner { // Constructor // ------------------------------------------------------------------------- - constructor(driver: MysqlDriver, mode: "master"|"slave" = "master") { + constructor(driver: MysqlDriver, mode: ReplicationMode) { super(); this.driver = driver; this.connection = driver.connection; @@ -519,7 +520,9 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner { * Creates a new columns from the column in the table. */ async addColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.addColumn(tableOrName, column)); + for (const column of columns) { + await this.addColumn(tableOrName, column); + } } /** @@ -734,7 +737,9 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner { * Changes a column in the table. */ async changeColumns(tableOrName: Table|string, changedColumns: { newColumn: TableColumn, oldColumn: TableColumn }[]): Promise { - await PromiseUtils.runInSequence(changedColumns, changedColumn => this.changeColumn(tableOrName, changedColumn.oldColumn, changedColumn.newColumn)); + for (const {oldColumn, newColumn} of changedColumns) { + await this.changeColumn(tableOrName, oldColumn, newColumn); + } } /** @@ -826,7 +831,9 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner { * Drops the columns in the table. */ async dropColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.dropColumn(tableOrName, column)); + for (const column of columns) { + await this.dropColumn(tableOrName, column); + } } /** @@ -1219,7 +1226,7 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner { return `(\`s\`.\`TABLE_SCHEMA\` = '${database}' AND \`s\`.\`TABLE_NAME\` = '${name}')`; }).join(" OR "); const indicesSql = `SELECT \`s\`.* FROM \`INFORMATION_SCHEMA\`.\`STATISTICS\` \`s\` ` + - `LEFT JOIN \`INFORMATION_SCHEMA\`.\`REFERENTIAL_CONSTRAINTS\` \`rc\` ON \`s\`.\`INDEX_NAME\` = \`rc\`.\`CONSTRAINT_NAME\` ` + + `LEFT JOIN \`INFORMATION_SCHEMA\`.\`REFERENTIAL_CONSTRAINTS\` \`rc\` ON \`s\`.\`INDEX_NAME\` = \`rc\`.\`CONSTRAINT_NAME\` AND \`s\`.\`TABLE_SCHEMA\` = \`rc\`.\`CONSTRAINT_SCHEMA\`` + `WHERE (${indicesCondition}) AND \`s\`.\`INDEX_NAME\` != 'PRIMARY' AND \`rc\`.\`CONSTRAINT_NAME\` IS NULL`; const foreignKeysCondition = tableNames.map(tableName => { @@ -1297,6 +1304,13 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner { tableColumn.name = dbColumn["COLUMN_NAME"]; tableColumn.type = dbColumn["DATA_TYPE"].toLowerCase(); + tableColumn.zerofill = dbColumn["COLUMN_TYPE"].indexOf("zerofill") !== -1; + tableColumn.unsigned = tableColumn.zerofill ? true : dbColumn["COLUMN_TYPE"].indexOf("unsigned") !== -1; + if (this.driver.withWidthColumnTypes.indexOf(tableColumn.type as ColumnType) !== -1) { + const width = dbColumn["COLUMN_TYPE"].substring(dbColumn["COLUMN_TYPE"].indexOf("(") + 1, dbColumn["COLUMN_TYPE"].indexOf(")")); + tableColumn.width = width && !this.isDefaultColumnWidth(table, tableColumn, parseInt(width)) ? parseInt(width) : undefined; + } + if (dbColumn["COLUMN_DEFAULT"] === null || dbColumn["COLUMN_DEFAULT"] === undefined || (isMariaDb && dbColumn["COLUMN_DEFAULT"] === "NULL")) { @@ -1315,7 +1329,9 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner { } if (dbColumn["EXTRA"].indexOf("on update") !== -1) { - tableColumn.onUpdate = dbColumn["EXTRA"].substring(dbColumn["EXTRA"].indexOf("on update") + 10); + // New versions of MariaDB return expressions in lowercase. We need to set it in + // uppercase so the comparison in MysqlDriver#compareExtraValues does not fail. + tableColumn.onUpdate = dbColumn["EXTRA"].substring(dbColumn["EXTRA"].indexOf("on update") + 10).toUpperCase(); } if (dbColumn["GENERATION_EXPRESSION"]) { @@ -1328,13 +1344,6 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner { tableColumn.isPrimary = dbPrimaryKeys.some(dbPrimaryKey => { return this.driver.buildTableName(dbPrimaryKey["TABLE_NAME"], undefined, dbPrimaryKey["TABLE_SCHEMA"]) === tableFullName && dbPrimaryKey["COLUMN_NAME"] === tableColumn.name; }); - tableColumn.zerofill = dbColumn["COLUMN_TYPE"].indexOf("zerofill") !== -1; - tableColumn.unsigned = tableColumn.zerofill ? true : dbColumn["COLUMN_TYPE"].indexOf("unsigned") !== -1; - if (this.driver.withWidthColumnTypes.indexOf(tableColumn.type as ColumnType) !== -1) { - const width = dbColumn["COLUMN_TYPE"].substring(dbColumn["COLUMN_TYPE"].indexOf("(") + 1, dbColumn["COLUMN_TYPE"].indexOf(")")); - tableColumn.width = width && !this.isDefaultColumnWidth(table, tableColumn, parseInt(width)) ? parseInt(width) : undefined; - } - tableColumn.isGenerated = dbColumn["EXTRA"].indexOf("auto_increment") !== -1; if (tableColumn.isGenerated) tableColumn.generationStrategy = "increment"; @@ -1681,7 +1690,7 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner { if (column.isGenerated && column.generationStrategy === "increment") // don't use skipPrimary here since updates can update already exist primary without auto inc. c += " AUTO_INCREMENT"; if (column.comment) - c += ` COMMENT '${column.comment}'`; + c += ` COMMENT '${column.comment.replace("'", "''")}'`; if (column.default !== undefined && column.default !== null) c += ` DEFAULT ${column.default}`; if (column.onUpdate) @@ -1695,4 +1704,35 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner { return result[0]["version"]; } + /** + * Checks if column display width is by default. + */ + protected isDefaultColumnWidth(table: Table, column: TableColumn, width: number): boolean { + // if table have metadata, we check if length is specified in column metadata + if (this.connection.hasMetadata(table.name)) { + const metadata = this.connection.getMetadata(table.name); + const columnMetadata = metadata.findColumnWithDatabaseName(column.name); + if (columnMetadata && columnMetadata.width) + return false; + } + + const defaultWidthForType = this.connection.driver.dataTypeDefaults + && this.connection.driver.dataTypeDefaults[column.type] + && this.connection.driver.dataTypeDefaults[column.type].width; + + if (defaultWidthForType) { + // In MariaDB & MySQL 5.7, the default widths of certain numeric types are 1 less than + // the usual defaults when the column is unsigned. + const typesWithReducedUnsignedDefault = ["int", "tinyint", "smallint", "mediumint"]; + const needsAdjustment = typesWithReducedUnsignedDefault.indexOf(column.type) !== -1; + if (column.unsigned && needsAdjustment) { + return (defaultWidthForType - 1) === width; + } else { + return defaultWidthForType === width; + } + } + + return false; + } + } diff --git a/src/driver/nativescript/NativescriptDriver.ts b/src/driver/nativescript/NativescriptDriver.ts index 93cc4409b5..fc2fd6e82d 100644 --- a/src/driver/nativescript/NativescriptDriver.ts +++ b/src/driver/nativescript/NativescriptDriver.ts @@ -6,6 +6,7 @@ import {Connection} from "../../connection/Connection"; import {DriverOptionNotSetError} from "../../error/DriverOptionNotSetError"; import {DriverPackageNotInstalledError} from "../../error/DriverPackageNotInstalledError"; import {ColumnType} from "../types/ColumnTypes"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with sqlite DBMS within Nativescript. @@ -66,7 +67,7 @@ export class NativescriptDriver extends AbstractSqliteDriver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master"): QueryRunner { + createQueryRunner(mode: ReplicationMode): QueryRunner { if (!this.queryRunner) { this.queryRunner = new NativescriptQueryRunner(this); } diff --git a/src/driver/oracle/OracleDriver.ts b/src/driver/oracle/OracleDriver.ts index 1bdabf03a8..c9af99497f 100644 --- a/src/driver/oracle/OracleDriver.ts +++ b/src/driver/oracle/OracleDriver.ts @@ -18,6 +18,7 @@ import {DriverUtils} from "../DriverUtils"; import {EntityMetadata} from "../../metadata/EntityMetadata"; import {OrmUtils} from "../../util/OrmUtils"; import {ApplyValueTransformers} from "../../util/ApplyValueTransformers"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with Oracle RDBMS. @@ -287,7 +288,7 @@ export class OracleDriver implements Driver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master") { + createQueryRunner(mode: ReplicationMode) { return new OracleQueryRunner(this, mode); } @@ -624,11 +625,18 @@ export class OracleDriver implements Driver { return false; } + /** + * Returns true if driver supports fulltext indices. + */ + isFullTextColumnTypeSupported(): boolean { + return false; + } + /** * Creates an escaped parameter. */ createParameter(parameterName: string, index: number): string { - return ":" + parameterName; + return ":" + (index + 1); } /** diff --git a/src/driver/oracle/OracleQueryRunner.ts b/src/driver/oracle/OracleQueryRunner.ts index 7f8c35cacb..0fc9af0378 100644 --- a/src/driver/oracle/OracleQueryRunner.ts +++ b/src/driver/oracle/OracleQueryRunner.ts @@ -18,9 +18,10 @@ import {Broadcaster} from "../../subscriber/Broadcaster"; import {BaseQueryRunner} from "../../query-runner/BaseQueryRunner"; import {OrmUtils} from "../../util/OrmUtils"; import {TableCheck} from "../../schema-builder/table/TableCheck"; -import {ColumnType, PromiseUtils} from "../../index"; +import {ColumnType} from "../../index"; import {IsolationLevel} from "../types/IsolationLevel"; import {TableExclusion} from "../../schema-builder/table/TableExclusion"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Runs queries on a single oracle database connection. @@ -49,7 +50,7 @@ export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner { // Constructor // ------------------------------------------------------------------------- - constructor(driver: OracleDriver, mode: "master"|"slave" = "master") { + constructor(driver: OracleDriver, mode: ReplicationMode) { super(); this.driver = driver; this.connection = driver.connection; @@ -507,7 +508,9 @@ export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner { * Creates a new columns from the column in the table. */ async addColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.addColumn(tableOrName, column)); + for (const column of columns) { + await this.addColumn(tableOrName, column); + } } /** @@ -734,7 +737,9 @@ export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner { * Changes a column in the table. */ async changeColumns(tableOrName: Table|string, changedColumns: { newColumn: TableColumn, oldColumn: TableColumn }[]): Promise { - await PromiseUtils.runInSequence(changedColumns, changedColumn => this.changeColumn(tableOrName, changedColumn.oldColumn, changedColumn.newColumn)); + for (const {oldColumn, newColumn} of changedColumns) { + await this.changeColumn(tableOrName, oldColumn, newColumn); + } } /** @@ -806,7 +811,9 @@ export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner { * Drops the columns in the table. */ async dropColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.dropColumn(tableOrName, column)); + for (const column of columns) { + await this.dropColumn(tableOrName, column); + } } /** @@ -1503,7 +1510,7 @@ export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner { `REFERENCES "${foreignKey.referencedTableName}" (${referencedColumnNames})`; // Oracle does not support NO ACTION, but we set NO ACTION by default in EntityMetadata if (foreignKey.onDelete && foreignKey.onDelete !== "NO ACTION") - sql += ` ON DELETE ${foreignKey.onDelete}`; + sql += ` ON DELETE ${foreignKey.onDelete}`; return new Query(sql); } diff --git a/src/driver/postgres/PostgresConnectionCredentialsOptions.ts b/src/driver/postgres/PostgresConnectionCredentialsOptions.ts index d20bac3846..3601670bce 100644 --- a/src/driver/postgres/PostgresConnectionCredentialsOptions.ts +++ b/src/driver/postgres/PostgresConnectionCredentialsOptions.ts @@ -28,7 +28,7 @@ export interface PostgresConnectionCredentialsOptions { /** * Database password. */ - readonly password?: string; + readonly password?: string | (() => string) | (() => Promise); /** * Database name to connect to. diff --git a/src/driver/postgres/PostgresConnectionOptions.ts b/src/driver/postgres/PostgresConnectionOptions.ts index aa70411217..908360df6d 100644 --- a/src/driver/postgres/PostgresConnectionOptions.ts +++ b/src/driver/postgres/PostgresConnectionOptions.ts @@ -33,6 +33,12 @@ export interface PostgresConnectionOptions extends BaseConnectionOptions, Postgr }; + /** + * The milliseconds before a timeout occurs during the initial connection to the postgres + * server. If undefined, or set to 0, there is no timeout. Defaults to undefined. + */ + readonly connectTimeoutMS?: number; + /** * The Postgres extension to use to generate UUID columns. Defaults to uuid-ossp. * If pgcrypto is selected, TypeORM will use the gen_random_uuid() function from this extension. @@ -46,4 +52,9 @@ export interface PostgresConnectionOptions extends BaseConnectionOptions, Postgr * Defaults to logging error with `warn` level. */ readonly poolErrorHandler?: (err: any) => any; + + /** + * Include notification messages from Postgres server in client logs + */ + readonly logNotifications?: boolean; } diff --git a/src/driver/postgres/PostgresDriver.ts b/src/driver/postgres/PostgresDriver.ts index a18c64be27..6e21ee57aa 100644 --- a/src/driver/postgres/PostgresDriver.ts +++ b/src/driver/postgres/PostgresDriver.ts @@ -19,6 +19,9 @@ import {PostgresConnectionCredentialsOptions} from "./PostgresConnectionCredenti import {EntityMetadata} from "../../metadata/EntityMetadata"; import {OrmUtils} from "../../util/OrmUtils"; import {ApplyValueTransformers} from "../../util/ApplyValueTransformers"; +import {AuroraDataApiPostgresConnectionOptions} from "../aurora-data-api-pg/AuroraDataApiPostgresConnectionOptions"; +import {AuroraDataApiPostgresQueryRunner} from "../aurora-data-api-pg/AuroraDataApiPostgresQueryRunner"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with PostgreSQL DBMS. @@ -149,7 +152,8 @@ export class PostgresDriver implements Driver { "daterange", "geometry", "geography", - "cube" + "cube", + "ltree" ]; /** @@ -248,7 +252,11 @@ export class PostgresDriver implements Driver { // Constructor // ------------------------------------------------------------------------- - constructor(connection: Connection) { + constructor(connection?: Connection) { + if (!connection) { + return; + } + this.connection = connection; this.options = connection.options as PostgresConnectionOptions; this.isReplicated = this.options.replication ? true : false; @@ -295,6 +303,83 @@ export class PostgresDriver implements Driver { * Makes any action after connection (e.g. create extensions in Postgres driver). */ async afterConnect(): Promise { + const extensionsMetadata = await this.checkMetadataForExtensions(); + + if (extensionsMetadata.hasExtensions) { + await Promise.all([this.master, ...this.slaves].map(pool => { + return new Promise((ok, fail) => { + pool.connect(async (err: any, connection: any, release: Function) => { + await this.enableExtensions(extensionsMetadata, connection); + if (err) return fail(err); + release(); + ok(); + }); + }); + })); + } + + return Promise.resolve(); + } + + protected async enableExtensions(extensionsMetadata: any, connection: any) { + const { logger } = this.connection; + + const { + hasUuidColumns, + hasCitextColumns, + hasHstoreColumns, + hasCubeColumns, + hasGeometryColumns, + hasLtreeColumns, + hasExclusionConstraints, + } = extensionsMetadata; + + if (hasUuidColumns) + try { + await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "${this.options.uuidExtension || "uuid-ossp"}"`); + } catch (_) { + logger.log("warn", `At least one of the entities has uuid column, but the '${this.options.uuidExtension || "uuid-ossp"}' extension cannot be installed automatically. Please install it manually using superuser rights, or select another uuid extension.`); + } + if (hasCitextColumns) + try { + await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "citext"`); + } catch (_) { + logger.log("warn", "At least one of the entities has citext column, but the 'citext' extension cannot be installed automatically. Please install it manually using superuser rights"); + } + if (hasHstoreColumns) + try { + await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "hstore"`); + } catch (_) { + logger.log("warn", "At least one of the entities has hstore column, but the 'hstore' extension cannot be installed automatically. Please install it manually using superuser rights"); + } + if (hasGeometryColumns) + try { + await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "postgis"`); + } catch (_) { + logger.log("warn", "At least one of the entities has a geometry column, but the 'postgis' extension cannot be installed automatically. Please install it manually using superuser rights"); + } + if (hasCubeColumns) + try { + await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "cube"`); + } catch (_) { + logger.log("warn", "At least one of the entities has a cube column, but the 'cube' extension cannot be installed automatically. Please install it manually using superuser rights"); + } + if (hasLtreeColumns) + try { + await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "ltree"`); + } catch (_) { + logger.log("warn", "At least one of the entities has a cube column, but the 'ltree' extension cannot be installed automatically. Please install it manually using superuser rights"); + } + if (hasExclusionConstraints) + try { + // The btree_gist extension provides operator support in PostgreSQL exclusion constraints + await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "btree_gist"`); + } catch (_) { + logger.log("warn", "At least one of the entities has an exclusion constraint, but the 'btree_gist' extension cannot be installed automatically. Please install it manually using superuser rights"); + } + } + + protected async checkMetadataForExtensions() { const hasUuidColumns = this.connection.entityMetadatas.some(metadata => { return metadata.generatedColumns.filter(column => column.generationStrategy === "uuid").length > 0; }); @@ -310,60 +395,23 @@ export class PostgresDriver implements Driver { const hasGeometryColumns = this.connection.entityMetadatas.some(metadata => { return metadata.columns.filter(column => this.spatialTypes.indexOf(column.type) >= 0).length > 0; }); + const hasLtreeColumns = this.connection.entityMetadatas.some(metadata => { + return metadata.columns.filter(column => column.type === 'ltree').length > 0; + }); const hasExclusionConstraints = this.connection.entityMetadatas.some(metadata => { return metadata.exclusions.length > 0; }); - if (hasUuidColumns || hasCitextColumns || hasHstoreColumns || hasGeometryColumns || hasCubeColumns || hasExclusionConstraints) { - await Promise.all([this.master, ...this.slaves].map(pool => { - return new Promise((ok, fail) => { - pool.connect(async (err: any, connection: any, release: Function) => { - const { logger } = this.connection; - if (err) return fail(err); - if (hasUuidColumns) - try { - await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "${this.options.uuidExtension || "uuid-ossp"}"`); - } catch (_) { - logger.log("warn", `At least one of the entities has uuid column, but the '${this.options.uuidExtension || "uuid-ossp"}' extension cannot be installed automatically. Please install it manually using superuser rights, or select another uuid extension.`); - } - if (hasCitextColumns) - try { - await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "citext"`); - } catch (_) { - logger.log("warn", "At least one of the entities has citext column, but the 'citext' extension cannot be installed automatically. Please install it manually using superuser rights"); - } - if (hasHstoreColumns) - try { - await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "hstore"`); - } catch (_) { - logger.log("warn", "At least one of the entities has hstore column, but the 'hstore' extension cannot be installed automatically. Please install it manually using superuser rights"); - } - if (hasGeometryColumns) - try { - await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "postgis"`); - } catch (_) { - logger.log("warn", "At least one of the entities has a geometry column, but the 'postgis' extension cannot be installed automatically. Please install it manually using superuser rights"); - } - if (hasCubeColumns) - try { - await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "cube"`); - } catch (_) { - logger.log("warn", "At least one of the entities has a cube column, but the 'cube' extension cannot be installed automatically. Please install it manually using superuser rights"); - } - if (hasExclusionConstraints) - try { - // The btree_gist extension provides operator support in PostgreSQL exclusion constraints - await this.executeQuery(connection, `CREATE EXTENSION IF NOT EXISTS "btree_gist"`); - } catch (_) { - logger.log("warn", "At least one of the entities has an exclusion constraint, but the 'btree_gist' extension cannot be installed automatically. Please install it manually using superuser rights"); - } - release(); - ok(); - }); - }); - })); - } - return Promise.resolve(); + return { + hasUuidColumns, + hasCitextColumns, + hasHstoreColumns, + hasCubeColumns, + hasGeometryColumns, + hasLtreeColumns, + hasExclusionConstraints, + hasExtensions: hasUuidColumns || hasCitextColumns || hasHstoreColumns || hasGeometryColumns || hasCubeColumns || hasLtreeColumns || hasExclusionConstraints, + }; } /** @@ -389,7 +437,7 @@ export class PostgresDriver implements Driver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master") { + createQueryRunner(mode: ReplicationMode): QueryRunner { return new PostgresQueryRunner(this, mode); } @@ -452,6 +500,8 @@ export class PostgresDriver implements Driver { } return `(${value.join(",")})`; + } else if (columnMetadata.type === "ltree") { + return value.split(".").filter(Boolean).join('.').replace(/[\s]+/g, "_"); } else if ( ( columnMetadata.type === "enum" @@ -863,6 +913,13 @@ export class PostgresDriver implements Driver { return true; } + /** + * Returns true if driver supports fulltext indices. + */ + isFullTextColumnTypeSupported(): boolean { + return false; + } + get uuidGenerator(): string { return this.options.uuidExtension === "pgcrypto" ? "gen_random_uuid()" : "uuid_generate_v4()"; } @@ -919,13 +976,15 @@ export class PostgresDriver implements Driver { credentials = Object.assign({}, credentials, DriverUtils.buildDriverOptions(credentials)); // todo: do it better way // build connection options for the driver + // See: https://github.com/brianc/node-postgres/tree/master/packages/pg-pool#create const connectionOptions = Object.assign({}, { host: credentials.host, user: credentials.username, password: credentials.password, database: credentials.database, port: credentials.port, - ssl: credentials.ssl + ssl: credentials.ssl, + connectionTimeoutMillis: options.connectTimeoutMS }, options.extra || {}); // create a connection pool @@ -943,6 +1002,15 @@ export class PostgresDriver implements Driver { return new Promise((ok, fail) => { pool.connect((err: any, connection: any, release: Function) => { if (err) return fail(err); + + if (options.logNotifications) { + connection.on("notice", (msg: any) => { + msg && this.connection.logger.log("info", msg.message); + }); + connection.on("notification", (msg: any) => { + msg && this.connection.logger.log("info", `Received NOTIFY on channel ${msg.channel}: ${msg.payload}.`); + }); + } release(); ok(pool); }); @@ -972,3 +1040,124 @@ export class PostgresDriver implements Driver { } } + +abstract class PostgresWrapper extends PostgresDriver { + options: any; + + abstract createQueryRunner(mode: ReplicationMode): any; +} + +export class AuroraDataApiPostgresDriver extends PostgresWrapper { + + // ------------------------------------------------------------------------- + // Public Properties + // ------------------------------------------------------------------------- + + /** + * Connection used by driver. + */ + connection: Connection; + + /** + * Aurora Data API underlying library. + */ + DataApiDriver: any; + + client: any; + + // ------------------------------------------------------------------------- + // Public Implemented Properties + // ------------------------------------------------------------------------- + + /** + * Connection options. + */ + options: AuroraDataApiPostgresConnectionOptions; + + /** + * Master database used to perform all write queries. + */ + database?: string; + + // ------------------------------------------------------------------------- + // Constructor + // ------------------------------------------------------------------------- + + constructor(connection: Connection) { + super(); + this.connection = connection; + this.options = connection.options as AuroraDataApiPostgresConnectionOptions; + this.isReplicated = false; + + // load data-api package + this.loadDependencies(); + + this.client = new this.DataApiDriver( + this.options.region, + this.options.secretArn, + this.options.resourceArn, + this.options.database, + (query: string, parameters?: any[]) => this.connection.logger.logQuery(query, parameters), + this.options.serviceConfigOptions, + this.options.formatOptions, + ); + } + + // ------------------------------------------------------------------------- + // Public Implemented Methods + // ------------------------------------------------------------------------- + + /** + * Performs connection to the database. + * Based on pooling options, it can either create connection immediately, + * either create a pool and create connection when needed. + */ + async connect(): Promise { + } + + /** + * Closes connection with database. + */ + async disconnect(): Promise { + } + + /** + * Creates a query runner used to execute database queries. + */ + createQueryRunner(mode: ReplicationMode) { + return new AuroraDataApiPostgresQueryRunner(this, mode); + } + + // ------------------------------------------------------------------------- + // Protected Methods + // ------------------------------------------------------------------------- + + /** + * If driver dependency is not given explicitly, then try to load it via "require". + */ + protected loadDependencies(): void { + const { pg } = PlatformTools.load("typeorm-aurora-data-api-driver"); + + this.DataApiDriver = pg; + } + + /** + * Executes given query. + */ + protected executeQuery(connection: any, query: string) { + return this.client.query(query); + } + + /** + * Makes any action after connection (e.g. create extensions in Postgres driver). + */ + async afterConnect(): Promise { + const extensionsMetadata = await this.checkMetadataForExtensions(); + + if (extensionsMetadata.hasExtensions) { + await this.enableExtensions(extensionsMetadata, this.connection); + } + + return Promise.resolve(); + } +} diff --git a/src/driver/postgres/PostgresQueryRunner.ts b/src/driver/postgres/PostgresQueryRunner.ts index 9fd1ef8db6..a8def64da2 100644 --- a/src/driver/postgres/PostgresQueryRunner.ts +++ b/src/driver/postgres/PostgresQueryRunner.ts @@ -1,4 +1,3 @@ -import {PromiseUtils} from "../../"; import {ObjectLiteral} from "../../common/ObjectLiteral"; import {QueryFailedError} from "../../error/QueryFailedError"; import {QueryRunnerAlreadyReleasedError} from "../../error/QueryRunnerAlreadyReleasedError"; @@ -23,6 +22,7 @@ import {OrmUtils} from "../../util/OrmUtils"; import {Query} from "../Query"; import {IsolationLevel} from "../types/IsolationLevel"; import {PostgresDriver} from "./PostgresDriver"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Runs queries on a single postgres database connection. @@ -56,7 +56,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner // Constructor // ------------------------------------------------------------------------- - constructor(driver: PostgresDriver, mode: "master"|"slave" = "master") { + constructor(driver: PostgresDriver, mode: ReplicationMode) { super(); this.driver = driver; this.connection = driver.connection; @@ -80,10 +80,17 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner return this.databaseConnectionPromise; if (this.mode === "slave" && this.driver.isReplicated) { - this.databaseConnectionPromise = this.driver.obtainSlaveConnection().then(([ connection, release]: any[]) => { + this.databaseConnectionPromise = this.driver.obtainSlaveConnection().then(([connection, release]: any[]) => { this.driver.connectedQueryRunners.push(this); this.databaseConnection = connection; - this.releaseCallback = release; + + const onErrorCallback = () => this.release(); + this.releaseCallback = () => { + this.databaseConnection.removeListener("error", onErrorCallback); + release(); + }; + this.databaseConnection.on("error", onErrorCallback); + return this.databaseConnection; }); @@ -91,7 +98,14 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner this.databaseConnectionPromise = this.driver.obtainMasterConnection().then(([connection, release]: any[]) => { this.driver.connectedQueryRunners.push(this); this.databaseConnection = connection; - this.releaseCallback = release; + + const onErrorCallback = () => this.release(); + this.releaseCallback = () => { + this.databaseConnection.removeListener("error", onErrorCallback); + release(); + }; + this.databaseConnection.on("error", onErrorCallback); + return this.databaseConnection; }); } @@ -104,6 +118,10 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner * You cannot use query runner methods once its released. */ release(): Promise { + if (this.isReleased) { + return Promise.resolve(); + } + this.isReleased = true; if (this.releaseCallback) this.releaseCallback(); @@ -166,7 +184,6 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner const queryStartTime = +new Date(); databaseConnection.query(query, parameters, (err: any, result: any) => { - // log slow queries if maxQueryExecution time is set const maxQueryExecutionTime = this.driver.connection.options.maxQueryExecutionTime; const queryEndTime = +new Date(); @@ -557,7 +574,9 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner * Creates a new columns from the column in the table. */ async addColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.addColumn(tableOrName, column)); + for (const column of columns) { + await this.addColumn(tableOrName, column); + } } /** @@ -875,7 +894,9 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner * Changes a column in the table. */ async changeColumns(tableOrName: Table|string, changedColumns: { newColumn: TableColumn, oldColumn: TableColumn }[]): Promise { - await PromiseUtils.runInSequence(changedColumns, changedColumn => this.changeColumn(tableOrName, changedColumn.oldColumn, changedColumn.newColumn)); + for (const {oldColumn, newColumn} of changedColumns) { + await this.changeColumn(tableOrName, oldColumn, newColumn); + } } /** @@ -959,7 +980,9 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner * Drops the columns in the table. */ async dropColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.dropColumn(tableOrName, column)); + for (const column of columns) { + await this.dropColumn(tableOrName, column); + } } /** @@ -1048,7 +1071,9 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner * Creates new unique constraints. */ async createUniqueConstraints(tableOrName: Table|string, uniqueConstraints: TableUnique[]): Promise { - await PromiseUtils.runInSequence(uniqueConstraints, uniqueConstraint => this.createUniqueConstraint(tableOrName, uniqueConstraint)); + for (const uniqueConstraint of uniqueConstraints) { + await this.createUniqueConstraint(tableOrName, uniqueConstraint); + } } /** @@ -1070,7 +1095,9 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner * Drops unique constraints. */ async dropUniqueConstraints(tableOrName: Table|string, uniqueConstraints: TableUnique[]): Promise { - await PromiseUtils.runInSequence(uniqueConstraints, uniqueConstraint => this.dropUniqueConstraint(tableOrName, uniqueConstraint)); + for (const uniqueConstraint of uniqueConstraints) { + await this.dropUniqueConstraint(tableOrName, uniqueConstraint); + } } /** @@ -1187,7 +1214,9 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner * Creates a new foreign keys. */ async createForeignKeys(tableOrName: Table|string, foreignKeys: TableForeignKey[]): Promise { - await PromiseUtils.runInSequence(foreignKeys, foreignKey => this.createForeignKey(tableOrName, foreignKey)); + for (const foreignKey of foreignKeys) { + await this.createForeignKey(tableOrName, foreignKey); + } } /** @@ -1209,7 +1238,9 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner * Drops a foreign keys from the table. */ async dropForeignKeys(tableOrName: Table|string, foreignKeys: TableForeignKey[]): Promise { - await PromiseUtils.runInSequence(foreignKeys, foreignKey => this.dropForeignKey(tableOrName, foreignKey)); + for (const foreignKey of foreignKeys) { + await this.dropForeignKey(tableOrName, foreignKey); + } } /** @@ -1232,7 +1263,9 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner * Creates a new indices */ async createIndices(tableOrName: Table|string, indices: TableIndex[]): Promise { - await PromiseUtils.runInSequence(indices, index => this.createIndex(tableOrName, index)); + for (const index of indices) { + await this.createIndex(tableOrName, index); + } } /** @@ -1254,7 +1287,9 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner * Drops an indices from the table. */ async dropIndices(tableOrName: Table|string, indices: TableIndex[]): Promise { - await PromiseUtils.runInSequence(indices, index => this.dropIndex(tableOrName, index)); + for (const index of indices) { + await this.dropIndex(tableOrName, index); + } } /** @@ -1425,7 +1460,6 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner this.query(indicesSql), this.query(foreignKeysSql), ]); - // if tables were not found in the db, no need to proceed if (!dbTables.length) return []; @@ -1434,9 +1468,10 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner return Promise.all(dbTables.map(async dbTable => { const table = new Table(); + const getSchemaFromKey = (dbObject: any, key: string) => dbObject[key] === currentSchema && !this.driver.options.schema ? undefined : dbObject[key]; // We do not need to join schema name, when database is by default. // In this case we need local variable `tableFullName` for below comparision. - const schema = dbTable["table_schema"] === currentSchema && !this.driver.options.schema ? undefined : dbTable["table_schema"]; + const schema = getSchemaFromKey(dbTable, "table_schema"); table.name = this.driver.buildTableName(dbTable["table_name"], schema); const tableFullName = this.driver.buildTableName(dbTable["table_name"], dbTable["table_schema"]); @@ -1502,7 +1537,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner "type" FROM "geometry_columns" ) AS _ - WHERE (${tablesCondition}) AND "column_name" = '${tableColumn.name}' AND "table_name" = '${table.name}'`; + WHERE (${tablesCondition}) AND "column_name" = '${tableColumn.name}' AND "table_name" = '${dbTable["table_name"]}'`; const results: ObjectLiteral[] = await this.query(geometryColumnSql); tableColumn.spatialFeatureType = results[0].type; @@ -1519,7 +1554,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner "type" FROM "geography_columns" ) AS _ - WHERE (${tablesCondition}) AND "column_name" = '${tableColumn.name}' AND "table_name" = '${table.name}'`; + WHERE (${tablesCondition}) AND "column_name" = '${tableColumn.name}' AND "table_name" = '${dbTable["table_name"]}'`; const results: ObjectLiteral[] = await this.query(geographyColumnSql); tableColumn.spatialFeatureType = results[0].type; @@ -1613,7 +1648,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner const foreignKeys = dbForeignKeys.filter(dbFk => dbFk["constraint_name"] === dbForeignKey["constraint_name"]); // if referenced table located in currently used schema, we don't need to concat schema name to table name. - const schema = dbForeignKey["referenced_table_schema"] === currentSchema ? undefined : dbForeignKey["referenced_table_schema"]; + const schema = getSchemaFromKey(dbForeignKey, "referenced_table_schema"); const referencedTableName = this.driver.buildTableName(dbForeignKey["referenced_table_name"], schema); return new TableForeignKey({ diff --git a/src/driver/react-native/ReactNativeDriver.ts b/src/driver/react-native/ReactNativeDriver.ts index 803ac93b79..0763c04d7d 100644 --- a/src/driver/react-native/ReactNativeDriver.ts +++ b/src/driver/react-native/ReactNativeDriver.ts @@ -5,10 +5,12 @@ import {QueryRunner} from "../../query-runner/QueryRunner"; import {Connection} from "../../connection/Connection"; import {DriverOptionNotSetError} from "../../error/DriverOptionNotSetError"; import {DriverPackageNotInstalledError} from "../../error/DriverPackageNotInstalledError"; +import {PlatformTools} from "../../platform/PlatformTools"; +import {ReplicationMode} from "../types/ReplicationMode"; export class ReactNativeDriver extends AbstractSqliteDriver { options: ReactNativeConnectionOptions; - + // ------------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------------- @@ -28,7 +30,7 @@ export class ReactNativeDriver extends AbstractSqliteDriver { // load sqlite package this.loadDependencies(); } - + // ------------------------------------------------------------------------- // Public Methods @@ -43,17 +45,17 @@ export class ReactNativeDriver extends AbstractSqliteDriver { this.databaseConnection.close(ok, fail); }); } - + /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master"): QueryRunner { + createQueryRunner(mode: ReplicationMode): QueryRunner { if (!this.queryRunner) this.queryRunner = new ReactNativeQueryRunner(this); return this.queryRunner; } - + // ------------------------------------------------------------------------- // Protected Methods // ------------------------------------------------------------------------- @@ -89,10 +91,10 @@ export class ReactNativeDriver extends AbstractSqliteDriver { */ protected loadDependencies(): void { try { - this.sqlite = require("react-native-sqlite-storage"); + this.sqlite = PlatformTools.load("react-native-sqlite-storage"); } catch (e) { throw new DriverPackageNotInstalledError("React-Native", "react-native-sqlite-storage"); } } -} \ No newline at end of file +} diff --git a/src/driver/sap/SapConnectionCredentialsOptions.ts b/src/driver/sap/SapConnectionCredentialsOptions.ts index d0a36c746d..a64ddcfee3 100644 --- a/src/driver/sap/SapConnectionCredentialsOptions.ts +++ b/src/driver/sap/SapConnectionCredentialsOptions.ts @@ -36,7 +36,7 @@ export interface SapConnectionCredentialsOptions { /** * Validate database certificate */ - readonly validateCertificate?: boolean; + readonly sslValidateCertificate?: boolean; /** * Key for encrypted connection diff --git a/src/driver/sap/SapDriver.ts b/src/driver/sap/SapDriver.ts index 491b003726..1ae1cfea3e 100644 --- a/src/driver/sap/SapDriver.ts +++ b/src/driver/sap/SapDriver.ts @@ -11,6 +11,7 @@ import {DataTypeDefaults} from "../types/DataTypeDefaults"; import {MappedColumnTypes} from "../types/MappedColumnTypes"; import {SapConnectionOptions} from "./SapConnectionOptions"; import {SapQueryRunner} from "./SapQueryRunner"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with SAP Hana DBMS. @@ -220,7 +221,7 @@ export class SapDriver implements Driver { if (this.options.database) dbParams.databaseName = this.options.database; if (this.options.encrypt) dbParams.encrypt = this.options.encrypt; - if (this.options.validateCertificate) dbParams.validateCertificate = this.options.validateCertificate; + if (this.options.sslValidateCertificate) dbParams.validateCertificate = this.options.sslValidateCertificate; if (this.options.key) dbParams.key = this.options.key; if (this.options.cert) dbParams.cert = this.options.cert; if (this.options.ca) dbParams.ca = this.options.ca; @@ -228,7 +229,7 @@ export class SapDriver implements Driver { // pool options const options: any = { min: this.options.pool && this.options.pool.min ? this.options.pool.min : 1, - max: this.options.pool && this.options.pool.max ? this.options.pool.max : 1, + max: this.options.pool && this.options.pool.max ? this.options.pool.max : 10, }; if (this.options.pool && this.options.pool.checkInterval) options.checkInterval = this.options.pool.checkInterval; @@ -273,7 +274,7 @@ export class SapDriver implements Driver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master") { + createQueryRunner(mode: ReplicationMode) { return new SapQueryRunner(this, mode); } @@ -283,6 +284,10 @@ export class SapDriver implements Driver { */ escapeQueryWithParameters(sql: string, parameters: ObjectLiteral, nativeParameters: ObjectLiteral): [string, any[]] { const builtParameters: any[] = Object.keys(nativeParameters).map(key => { + + if (nativeParameters[key] instanceof Date) + return DateUtils.mixedDateToDatetimeString(nativeParameters[key], true); + return nativeParameters[key]; }); @@ -310,6 +315,9 @@ export class SapDriver implements Driver { } else if (value instanceof Function) { return value(); + } else if (value instanceof Date) { + return DateUtils.mixedDateToDatetimeString(value, true); + } else { builtParameters.push(value); return "?"; @@ -573,15 +581,15 @@ export class SapDriver implements Driver { // console.log("table:", columnMetadata.entityMetadata.tableName); // console.log("name:", tableColumn.name, columnMetadata.databaseName); - // console.log("type:", tableColumn.type, this.normalizeType(columnMetadata)); - // console.log("length:", tableColumn.length, columnMetadata.length); + // console.log("type:", tableColumn.type, _this.normalizeType(columnMetadata)); + // console.log("length:", tableColumn.length, _this.getColumnLength(columnMetadata)); // console.log("width:", tableColumn.width, columnMetadata.width); // console.log("precision:", tableColumn.precision, columnMetadata.precision); // console.log("scale:", tableColumn.scale, columnMetadata.scale); // console.log("default:", tableColumn.default, columnMetadata.default); // console.log("isPrimary:", tableColumn.isPrimary, columnMetadata.isPrimary); // console.log("isNullable:", tableColumn.isNullable, columnMetadata.isNullable); - // console.log("isUnique:", tableColumn.isUnique, this.normalizeIsUnique(columnMetadata)); + // console.log("isUnique:", tableColumn.isUnique, _this.normalizeIsUnique(columnMetadata)); // console.log("isGenerated:", tableColumn.isGenerated, columnMetadata.isGenerated); // console.log((columnMetadata.generationStrategy !== "uuid" && tableColumn.isGenerated !== columnMetadata.isGenerated)); // console.log("=========================================="); @@ -589,9 +597,9 @@ export class SapDriver implements Driver { const normalizeDefault = this.normalizeDefault(columnMetadata); const hanaNullComapatibleDefault = normalizeDefault == null ? undefined : normalizeDefault; - return tableColumn.name !== columnMetadata.databaseName + return tableColumn.name !== columnMetadata.databaseName || tableColumn.type !== this.normalizeType(columnMetadata) - || tableColumn.length !== columnMetadata.length + || columnMetadata.length && tableColumn.length !== this.getColumnLength(columnMetadata) || tableColumn.precision !== columnMetadata.precision || tableColumn.scale !== columnMetadata.scale // || tableColumn.comment !== columnMetadata.comment || // todo @@ -599,7 +607,7 @@ export class SapDriver implements Driver { || tableColumn.isPrimary !== columnMetadata.isPrimary || tableColumn.isNullable !== columnMetadata.isNullable || tableColumn.isUnique !== this.normalizeIsUnique(columnMetadata) - || tableColumn.isGenerated !== columnMetadata.isGenerated; + || (columnMetadata.generationStrategy !== "uuid" && tableColumn.isGenerated !== columnMetadata.isGenerated); }); } @@ -617,6 +625,13 @@ export class SapDriver implements Driver { return false; } + /** + * Returns true if driver supports fulltext indices. + */ + isFullTextColumnTypeSupported(): boolean { + return true; + } + /** * Creates an escaped parameter. */ diff --git a/src/driver/sap/SapQueryRunner.ts b/src/driver/sap/SapQueryRunner.ts index c3d606b8c4..d070176d9d 100644 --- a/src/driver/sap/SapQueryRunner.ts +++ b/src/driver/sap/SapQueryRunner.ts @@ -2,7 +2,7 @@ import {ObjectLiteral} from "../../common/ObjectLiteral"; import {QueryRunnerAlreadyReleasedError} from "../../error/QueryRunnerAlreadyReleasedError"; import {TransactionAlreadyStartedError} from "../../error/TransactionAlreadyStartedError"; import {TransactionNotStartedError} from "../../error/TransactionNotStartedError"; -import {ColumnType, PromiseUtils, QueryFailedError} from "../../index"; +import {ColumnType, QueryFailedError} from "../../index"; import {ReadStream} from "../../platform/PlatformTools"; import {BaseQueryRunner} from "../../query-runner/BaseQueryRunner"; import {QueryRunner} from "../../query-runner/QueryRunner"; @@ -20,6 +20,7 @@ import {OrmUtils} from "../../util/OrmUtils"; import {Query} from "../Query"; import {IsolationLevel} from "../types/IsolationLevel"; import {SapDriver} from "./SapDriver"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Runs queries on a single SQL Server database connection. @@ -55,7 +56,7 @@ export class SapQueryRunner extends BaseQueryRunner implements QueryRunner { // Constructor // ------------------------------------------------------------------------- - constructor(driver: SapDriver, mode: "master"|"slave" = "master") { + constructor(driver: SapDriver, mode: ReplicationMode) { super(); this.driver = driver; this.connection = driver.connection; @@ -91,7 +92,7 @@ export class SapQueryRunner extends BaseQueryRunner implements QueryRunner { return this.driver.master.release(this.databaseConnection); } - return Promise.resolve(); + return Promise.resolve(); } /** @@ -633,7 +634,9 @@ export class SapQueryRunner extends BaseQueryRunner implements QueryRunner { * Creates a new columns from the column in the table. */ async addColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.addColumn(tableOrName, column)); + for (const column of columns) { + await this.addColumn(tableOrName, column); + } } /** @@ -869,7 +872,9 @@ export class SapQueryRunner extends BaseQueryRunner implements QueryRunner { * Changes a column in the table. */ async changeColumns(tableOrName: Table|string, changedColumns: { newColumn: TableColumn, oldColumn: TableColumn }[]): Promise { - await PromiseUtils.runInSequence(changedColumns, changedColumn => this.changeColumn(tableOrName, changedColumn.oldColumn, changedColumn.newColumn)); + for (const {oldColumn, newColumn} of changedColumns) { + await this.changeColumn(tableOrName, oldColumn, newColumn) + } } /** @@ -989,7 +994,9 @@ export class SapQueryRunner extends BaseQueryRunner implements QueryRunner { * Drops the columns in the table. */ async dropColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.dropColumn(tableOrName, column)); + for (const column of columns) { + await this.dropColumn(tableOrName, column); + } } /** @@ -1447,7 +1454,7 @@ export class SapQueryRunner extends BaseQueryRunner implements QueryRunner { return `("SCHEMA_NAME" = '${schema}' AND "TABLE_NAME" = '${name}')`; }).join(" OR "); const tablesSql = `SELECT * FROM "SYS"."TABLES" WHERE ` + tablesCondition; - const columnsSql = `SELECT * FROM "SYS"."TABLE_COLUMNS" WHERE ` + tablesCondition; + const columnsSql = `SELECT * FROM "SYS"."TABLE_COLUMNS" WHERE ` + tablesCondition + ` ORDER BY "POSITION"`; const constraintsCondition = tableNames.map(tableName => { let [schema, name] = tableName.split("."); @@ -1458,7 +1465,7 @@ export class SapQueryRunner extends BaseQueryRunner implements QueryRunner { return `("SCHEMA_NAME" = '${schema}' AND "TABLE_NAME" = '${name}')`; }).join(" OR "); - const constraintsSql = `SELECT * FROM "SYS"."CONSTRAINTS" WHERE (${constraintsCondition})`; + const constraintsSql = `SELECT * FROM "SYS"."CONSTRAINTS" WHERE (${constraintsCondition}) ORDER BY "POSITION"`; const indicesCondition = tableNames.map(tableName => { let [schema, name] = tableName.split("."); @@ -1471,7 +1478,7 @@ export class SapQueryRunner extends BaseQueryRunner implements QueryRunner { // excluding primary key and autogenerated fulltext indices const indicesSql = `SELECT "I"."INDEX_TYPE", "I"."SCHEMA_NAME", "I"."TABLE_NAME", "I"."INDEX_NAME", "IC"."COLUMN_NAME", "I"."CONSTRAINT" ` + `FROM "SYS"."INDEXES" "I" INNER JOIN "SYS"."INDEX_COLUMNS" "IC" ON "IC"."INDEX_OID" = "I"."INDEX_OID" ` + - `WHERE (${indicesCondition}) AND ("I"."CONSTRAINT" IS NULL OR "I"."CONSTRAINT" != 'PRIMARY KEY') AND "I"."INDEX_NAME" NOT LIKE '%_SYS_FULLTEXT_%'`; + `WHERE (${indicesCondition}) AND ("I"."CONSTRAINT" IS NULL OR "I"."CONSTRAINT" != 'PRIMARY KEY') AND "I"."INDEX_NAME" NOT LIKE '%_SYS_FULLTEXT_%' ORDER BY "IC"."POSITION"`; const foreignKeysCondition = tableNames.map(tableName => { let [schema, name] = tableName.split("."); @@ -1481,7 +1488,7 @@ export class SapQueryRunner extends BaseQueryRunner implements QueryRunner { } return `("SCHEMA_NAME" = '${schema}' AND "TABLE_NAME" = '${name}')`; }).join(" OR "); - const foreignKeysSql = `SELECT * FROM "SYS"."REFERENTIAL_CONSTRAINTS" WHERE (${foreignKeysCondition})`; + const foreignKeysSql = `SELECT * FROM "SYS"."REFERENTIAL_CONSTRAINTS" WHERE (${foreignKeysCondition}) ORDER BY "POSITION"`; const [dbTables, dbColumns, dbConstraints, dbIndices, dbForeignKeys]: ObjectLiteral[][] = await Promise.all([ this.query(tablesSql), this.query(columnsSql), @@ -1823,7 +1830,7 @@ export class SapQueryRunner extends BaseQueryRunner implements QueryRunner { let indexType = ""; if (index.isUnique) { indexType += "UNIQUE "; - } + } if (index.isFulltext) { indexType += "FULLTEXT "; } diff --git a/src/driver/sqlite-abstract/AbstractSqliteDriver.ts b/src/driver/sqlite-abstract/AbstractSqliteDriver.ts index f5a7efe4af..55db1a1c5f 100644 --- a/src/driver/sqlite-abstract/AbstractSqliteDriver.ts +++ b/src/driver/sqlite-abstract/AbstractSqliteDriver.ts @@ -13,6 +13,7 @@ import {BaseConnectionOptions} from "../../connection/BaseConnectionOptions"; import {EntityMetadata} from "../../metadata/EntityMetadata"; import {OrmUtils} from "../../util/OrmUtils"; import {ApplyValueTransformers} from "../../util/ApplyValueTransformers"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with sqlite DBMS. @@ -130,12 +131,31 @@ export abstract class AbstractSqliteDriver implements Driver { /** * Gets list of column data types that support precision by a driver. */ - withPrecisionColumnTypes: ColumnType[] = []; + withPrecisionColumnTypes: ColumnType[] = [ + "real", + "double", + "double precision", + "float", + "real", + "numeric", + "decimal", + "date", + "time", + "datetime" + ]; /** * Gets list of column data types that support scale by a driver. */ - withScaleColumnTypes: ColumnType[] = []; + withScaleColumnTypes: ColumnType[] = [ + "real", + "double", + "double precision", + "float", + "real", + "numeric", + "decimal", + ]; /** * Orm has special columns and we need to know what database column types should be for those types. @@ -195,7 +215,7 @@ export abstract class AbstractSqliteDriver implements Driver { /** * Creates a query runner used to execute database queries. */ - abstract createQueryRunner(mode: "master"|"slave"): QueryRunner; + abstract createQueryRunner(mode: ReplicationMode): QueryRunner; // ------------------------------------------------------------------------- // Public Methods @@ -507,11 +527,13 @@ export abstract class AbstractSqliteDriver implements Driver { /** * Creates generated map of values generated or returned by database after INSERT query. */ - createGeneratedMap(metadata: EntityMetadata, insertResult: any) { + createGeneratedMap(metadata: EntityMetadata, insertResult: any, entityIndex: number, entityNum: number) { const generatedMap = metadata.generatedColumns.reduce((map, generatedColumn) => { let value: any; if (generatedColumn.generationStrategy === "increment" && insertResult) { - value = insertResult; + // NOTE: When INSERT statement is successfully completed, the last inserted row ID is returned. + // see also: SqliteQueryRunner.query() + value = insertResult - entityNum + entityIndex + 1; // } else if (generatedColumn.generationStrategy === "uuid") { // value = insertValue[generatedColumn.databaseName]; } @@ -576,6 +598,13 @@ export abstract class AbstractSqliteDriver implements Driver { return false; } + /** + * Returns true if driver supports fulltext indices. + */ + isFullTextColumnTypeSupported(): boolean { + return false; + } + /** * Creates an escaped parameter. */ diff --git a/src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts b/src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts index a5ce81ee44..1d0edb2d19 100644 --- a/src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts +++ b/src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts @@ -10,7 +10,6 @@ import {TableIndex} from "../../schema-builder/table/TableIndex"; import {TableForeignKey} from "../../schema-builder/table/TableForeignKey"; import {View} from "../../schema-builder/view/View"; import {Query} from "../Query"; -import {SqliteConnectionOptions} from "../sqlite/SqliteConnectionOptions"; import {AbstractSqliteDriver} from "./AbstractSqliteDriver"; import {ReadStream} from "../../platform/PlatformTools"; import {TableIndexOptions} from "../../schema-builder/options/TableIndexOptions"; @@ -69,19 +68,8 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen * Starts transaction. */ async startTransaction(isolationLevel?: IsolationLevel): Promise { - if (this.isTransactionActive) { - const options = this.driver.options as SqliteConnectionOptions; - if (options.busyErrorRetry && typeof options.busyErrorRetry === "number") { - return new Promise((ok, fail) => { - setTimeout( - () => this.startTransaction(isolationLevel).then(ok).catch(fail), - options.busyErrorRetry as number - ); - }); - } else { - throw new TransactionAlreadyStartedError(); - } - } + if (this.isTransactionActive) + throw new TransactionAlreadyStartedError(); this.isTransactionActive = true; @@ -97,10 +85,6 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen } } - if ((this.connection.options as SqliteConnectionOptions).enableWAL === true) { - await this.query("PRAGMA journal_mode = WAL"); - } - await this.query("BEGIN TRANSACTION"); } @@ -842,17 +826,31 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen } } - // parse datatype and attempt to retrieve length + // parse datatype and attempt to retrieve length, precision and scale let pos = tableColumn.type.indexOf("("); if (pos !== -1) { - let dataType = tableColumn.type.substr(0, pos); + const fullType = tableColumn.type; + let dataType = fullType.substr(0, pos); if (!!this.driver.withLengthColumnTypes.find(col => col === dataType)) { - let len = parseInt(tableColumn.type.substring(pos + 1, tableColumn.type.length - 1)); + let len = parseInt(fullType.substring(pos + 1, fullType.length - 1)); if (len) { tableColumn.length = len.toString(); tableColumn.type = dataType; // remove the length part from the datatype } } + if (!!this.driver.withPrecisionColumnTypes.find(col => col === dataType)) { + const re = new RegExp(`^${dataType}\\((\\d+),?\\s?(\\d+)?\\)`); + const matches = fullType.match(re); + if (matches && matches[1]) { + tableColumn.precision = +matches[1]; + } + if (!!this.driver.withScaleColumnTypes.find(col => col === dataType)) { + if (matches && matches[2]) { + tableColumn.scale = +matches[2]; + } + } + tableColumn.type = dataType; // remove the precision/scale part from the datatype + } } return tableColumn; diff --git a/src/driver/sqlite/SqliteConnectionOptions.ts b/src/driver/sqlite/SqliteConnectionOptions.ts index 8534fc5a76..8e092b9c69 100644 --- a/src/driver/sqlite/SqliteConnectionOptions.ts +++ b/src/driver/sqlite/SqliteConnectionOptions.ts @@ -31,7 +31,7 @@ export interface SqliteConnectionOptions extends BaseConnectionOptions { * Enabling WAL can improve your app performance and face less SQLITE_BUSY issues. * Time in milliseconds. */ - readonly busyErrorRetry?: number; // todo: implement this option for all SQLite family drivers + readonly busyErrorRetry?: number; /** * Enables WAL mode. By default its disabled. @@ -40,4 +40,4 @@ export interface SqliteConnectionOptions extends BaseConnectionOptions { */ readonly enableWAL?: boolean; -} \ No newline at end of file +} diff --git a/src/driver/sqlite/SqliteDriver.ts b/src/driver/sqlite/SqliteDriver.ts index 064039df04..585facffe1 100644 --- a/src/driver/sqlite/SqliteDriver.ts +++ b/src/driver/sqlite/SqliteDriver.ts @@ -1,12 +1,15 @@ -import {DriverPackageNotInstalledError} from "../../error/DriverPackageNotInstalledError"; -import {SqliteQueryRunner} from "./SqliteQueryRunner"; -import {DriverOptionNotSetError} from "../../error/DriverOptionNotSetError"; -import {PlatformTools} from "../../platform/PlatformTools"; -import {Connection} from "../../connection/Connection"; -import {SqliteConnectionOptions} from "./SqliteConnectionOptions"; -import {ColumnType} from "../types/ColumnTypes"; -import {QueryRunner} from "../../query-runner/QueryRunner"; -import {AbstractSqliteDriver} from "../sqlite-abstract/AbstractSqliteDriver"; +import mkdirp from 'mkdirp'; +import path from 'path'; +import { DriverPackageNotInstalledError } from "../../error/DriverPackageNotInstalledError"; +import { SqliteQueryRunner } from "./SqliteQueryRunner"; +import { DriverOptionNotSetError } from "../../error/DriverOptionNotSetError"; +import { PlatformTools } from "../../platform/PlatformTools"; +import { Connection } from "../../connection/Connection"; +import { SqliteConnectionOptions } from "./SqliteConnectionOptions"; +import { ColumnType } from "../types/ColumnTypes"; +import { QueryRunner } from "../../query-runner/QueryRunner"; +import { AbstractSqliteDriver } from "../sqlite-abstract/AbstractSqliteDriver"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with sqlite DBMS. @@ -63,7 +66,7 @@ export class SqliteDriver extends AbstractSqliteDriver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master"): QueryRunner { + createQueryRunner(mode: ReplicationMode): QueryRunner { if (!this.queryRunner) this.queryRunner = new SqliteQueryRunner(this); @@ -105,6 +108,10 @@ export class SqliteDriver extends AbstractSqliteDriver { }); } + if (this.options.enableWAL) { + await run(`PRAGMA journal_mode = WAL;`); + } + // we need to enable foreign keys in sqlite to make sure all foreign key related features // working properly. this also makes onDelete to work with sqlite. await run(`PRAGMA foreign_keys = ON;`); @@ -132,12 +139,8 @@ export class SqliteDriver extends AbstractSqliteDriver { /** * Auto creates database directory if it does not exist. */ - protected createDatabaseDirectory(fullPath: string): Promise { - return new Promise((resolve, reject) => { - const mkdirp = PlatformTools.load("mkdirp"); - const path = PlatformTools.load("path"); - mkdirp(path.dirname(fullPath), (err: any) => err ? reject(err) : resolve()); - }); + protected async createDatabaseDirectory(fullPath: string): Promise { + await mkdirp(path.dirname(fullPath)); } } diff --git a/src/driver/sqlite/SqliteQueryRunner.ts b/src/driver/sqlite/SqliteQueryRunner.ts index d1ac916d7d..308bb72855 100644 --- a/src/driver/sqlite/SqliteQueryRunner.ts +++ b/src/driver/sqlite/SqliteQueryRunner.ts @@ -55,11 +55,8 @@ export class SqliteQueryRunner extends AbstractSqliteQueryRunner { }; const handler = function (err: any, result: any) { - - if (err) { - if (err.toString().indexOf("SQLITE_BUSY:") !== -1 && - typeof options.busyErrorRetry === "number" && - options.busyErrorRetry) { + if (err && err.toString().indexOf("SQLITE_BUSY:") !== -1) { + if (typeof options.busyErrorRetry === "number" && options.busyErrorRetry > 0) { setTimeout(execute, options.busyErrorRetry); return; } @@ -83,4 +80,4 @@ export class SqliteQueryRunner extends AbstractSqliteQueryRunner { await execute(); }); } -} \ No newline at end of file +} diff --git a/src/driver/sqljs/SqljsDriver.ts b/src/driver/sqljs/SqljsDriver.ts index d1cf4994ff..ef06346ca8 100644 --- a/src/driver/sqljs/SqljsDriver.ts +++ b/src/driver/sqljs/SqljsDriver.ts @@ -9,6 +9,7 @@ import {PlatformTools} from "../../platform/PlatformTools"; import {EntityMetadata} from "../../metadata/EntityMetadata"; import {OrmUtils} from "../../util/OrmUtils"; import {ObjectLiteral} from "../../common/ObjectLiteral"; +import {ReplicationMode} from "../types/ReplicationMode"; // This is needed to satisfy the typescript compiler. interface Window { @@ -69,13 +70,13 @@ export class SqljsDriver extends AbstractSqliteDriver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master" | "slave" = "master"): QueryRunner { + createQueryRunner(mode: ReplicationMode): QueryRunner { if (!this.queryRunner) this.queryRunner = new SqljsQueryRunner(this); return this.queryRunner; } - + /** * Loads a database from a given file (Node.js), local storage key (browser) or array. * This will delete the current database! @@ -99,7 +100,7 @@ export class SqljsDriver extends AbstractSqliteDriver { // File will be written on first write operation. return this.createDatabaseConnectionWithImport(); } - } + } else { // browser // fileNameOrLocalStorageOrData should be a local storage / indexedDB key @@ -113,7 +114,7 @@ export class SqljsDriver extends AbstractSqliteDriver { } else { localStorageContent = PlatformTools.getGlobalVariable().localStorage.getItem(fileNameOrLocalStorageOrData); } - + if (localStorageContent != null) { // localStorage value exists. return this.createDatabaseConnectionWithImport(JSON.parse(localStorageContent)); @@ -143,7 +144,7 @@ export class SqljsDriver extends AbstractSqliteDriver { if (!location && !this.options.location) { throw new Error(`No location is set, specify a location parameter or add the location option to your configuration`); } - + let path = ""; if (location) { path = location; @@ -154,7 +155,7 @@ export class SqljsDriver extends AbstractSqliteDriver { if (PlatformTools.type === "node") { try { - const content = new Buffer(this.databaseConnection.export()); + const content = Buffer.from(this.databaseConnection.export()); await PlatformTools.writeFile(path, content); } catch (e) { @@ -193,7 +194,7 @@ export class SqljsDriver extends AbstractSqliteDriver { } } } - + /** * Returns the current database as Uint8Array. */ @@ -284,4 +285,4 @@ export class SqljsDriver extends AbstractSqliteDriver { } } } -} \ No newline at end of file +} diff --git a/src/driver/sqljs/SqljsQueryRunner.ts b/src/driver/sqljs/SqljsQueryRunner.ts index a3448e21ad..69a6349c47 100644 --- a/src/driver/sqljs/SqljsQueryRunner.ts +++ b/src/driver/sqljs/SqljsQueryRunner.ts @@ -41,7 +41,7 @@ export class SqljsQueryRunner extends AbstractSqliteQueryRunner { /** * Executes a given SQL query. */ - query(query: string, parameters?: any[]): Promise { + query(query: string, parameters: any[] = []): Promise { if (this.isReleased) throw new QueryRunnerAlreadyReleasedError(); @@ -52,7 +52,11 @@ export class SqljsQueryRunner extends AbstractSqliteQueryRunner { let statement: any; try { statement = databaseConnection.prepare(query); - statement.bind(parameters); + if (parameters) { + parameters = parameters.map(p => typeof p !== 'undefined' ? p : null); + + statement.bind(parameters); + } // log slow queries if maxQueryExecution time is set const maxQueryExecutionTime = this.driver.connection.options.maxQueryExecutionTime; diff --git a/src/driver/sqlserver/SqlServerDriver.ts b/src/driver/sqlserver/SqlServerDriver.ts index 313f6954bd..45ac48e933 100644 --- a/src/driver/sqlserver/SqlServerDriver.ts +++ b/src/driver/sqlserver/SqlServerDriver.ts @@ -19,6 +19,7 @@ import {SqlServerConnectionCredentialsOptions} from "./SqlServerConnectionCreden import {EntityMetadata} from "../../metadata/EntityMetadata"; import {OrmUtils} from "../../util/OrmUtils"; import {ApplyValueTransformers} from "../../util/ApplyValueTransformers"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Organizes communication with SQL Server DBMS. @@ -296,7 +297,7 @@ export class SqlServerDriver implements Driver { /** * Creates a query runner used to execute database queries. */ - createQueryRunner(mode: "master"|"slave" = "master") { + createQueryRunner(mode: ReplicationMode) { return new SqlServerQueryRunner(this, mode); } @@ -642,6 +643,13 @@ export class SqlServerDriver implements Driver { return true; } + /** + * Returns true if driver supports fulltext indices. + */ + isFullTextColumnTypeSupported(): boolean { + return false; + } + /** * Creates an escaped parameter. */ diff --git a/src/driver/sqlserver/SqlServerQueryRunner.ts b/src/driver/sqlserver/SqlServerQueryRunner.ts index 94575025e4..cb3b1eac86 100644 --- a/src/driver/sqlserver/SqlServerQueryRunner.ts +++ b/src/driver/sqlserver/SqlServerQueryRunner.ts @@ -4,7 +4,7 @@ import {QueryRunnerAlreadyReleasedError} from "../../error/QueryRunnerAlreadyRel import {TransactionAlreadyStartedError} from "../../error/TransactionAlreadyStartedError"; import {TransactionNotStartedError} from "../../error/TransactionNotStartedError"; import {NotImplementedError} from "../../error/NotImplementedError"; -import {ColumnType, PromiseUtils} from "../../index"; +import {ColumnType} from "../../index"; import {ReadStream} from "../../platform/PlatformTools"; import {BaseQueryRunner} from "../../query-runner/BaseQueryRunner"; import {QueryRunner} from "../../query-runner/QueryRunner"; @@ -23,6 +23,7 @@ import {Query} from "../Query"; import {IsolationLevel} from "../types/IsolationLevel"; import {MssqlParameter} from "./MssqlParameter"; import {SqlServerDriver} from "./SqlServerDriver"; +import {ReplicationMode} from "../types/ReplicationMode"; /** * Runs queries on a single SQL Server database connection. @@ -55,7 +56,7 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner // Constructor // ------------------------------------------------------------------------- - constructor(driver: SqlServerDriver, mode: "master"|"slave" = "master") { + constructor(driver: SqlServerDriver, mode: ReplicationMode) { super(); this.driver = driver; this.connection = driver.connection; @@ -360,7 +361,7 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner async hasColumn(tableOrName: Table|string, columnName: string): Promise { const parsedTableName = this.parseTableName(tableOrName); const schema = parsedTableName.schema === "SCHEMA_NAME()" ? parsedTableName.schema : `'${parsedTableName.schema}'`; - const sql = `SELECT * FROM "${parsedTableName.database}"."INFORMATION_SCHEMA"."TABLES" WHERE "TABLE_NAME" = '${parsedTableName.name}' AND "COLUMN_NAME" = '${columnName}' AND "TABLE_SCHEMA" = ${schema}`; + const sql = `SELECT * FROM "${parsedTableName.database}"."INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = '${parsedTableName.name}' AND "COLUMN_NAME" = '${columnName}' AND "TABLE_SCHEMA" = ${schema}`; const result = await this.query(sql); return result.length ? true : false; } @@ -710,7 +711,9 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner * Creates a new columns from the column in the table. */ async addColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.addColumn(tableOrName, column)); + for (const column of columns) { + await this.addColumn(tableOrName, column); + } } /** @@ -977,7 +980,9 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner * Changes a column in the table. */ async changeColumns(tableOrName: Table|string, changedColumns: { newColumn: TableColumn, oldColumn: TableColumn }[]): Promise { - await PromiseUtils.runInSequence(changedColumns, changedColumn => this.changeColumn(tableOrName, changedColumn.oldColumn, changedColumn.newColumn)); + for (const {oldColumn, newColumn} of changedColumns) { + await this.changeColumn(tableOrName, oldColumn, newColumn); + } } /** @@ -1057,7 +1062,9 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner * Drops the columns in the table. */ async dropColumns(tableOrName: Table|string, columns: TableColumn[]): Promise { - await PromiseUtils.runInSequence(columns, column => this.dropColumn(tableOrName, column)); + for (const column of columns) { + await this.dropColumn(tableOrName, column); + } } /** diff --git a/src/driver/types/ColumnTypes.ts b/src/driver/types/ColumnTypes.ts index 3569bedda3..44c3ab2b85 100644 --- a/src/driver/types/ColumnTypes.ts +++ b/src/driver/types/ColumnTypes.ts @@ -193,7 +193,8 @@ export type SimpleColumnType = |"uniqueidentifier" // mssql |"rowversion" // mssql |"array" // cockroachdb, sap - |"cube"; // postgres + |"cube" // postgres + |"ltree"; // postgres /** * Any column type column can be. diff --git a/src/driver/types/DatabaseType.ts b/src/driver/types/DatabaseType.ts index 68a3045013..5ceaece0cc 100644 --- a/src/driver/types/DatabaseType.ts +++ b/src/driver/types/DatabaseType.ts @@ -16,4 +16,6 @@ export type DatabaseType = "mssql"| "mongodb"| "aurora-data-api"| - "expo"; + "aurora-data-api-pg"| + "expo"| + "better-sqlite3"; diff --git a/src/driver/types/ReplicationMode.ts b/src/driver/types/ReplicationMode.ts new file mode 100644 index 0000000000..53aca0d997 --- /dev/null +++ b/src/driver/types/ReplicationMode.ts @@ -0,0 +1 @@ +export type ReplicationMode = "master" | "slave"; diff --git a/src/entity-manager/EntityManager.ts b/src/entity-manager/EntityManager.ts index 5ad6f03283..9df6eae40e 100644 --- a/src/entity-manager/EntityManager.ts +++ b/src/entity-manager/EntityManager.ts @@ -1,23 +1,22 @@ +import {Connection} from "../connection/Connection"; +import {EntityTarget} from "../common/EntityTarget"; +import {ObjectType} from "../common/ObjectType"; +import {DeepPartial} from "../common/DeepPartial"; +import {RemoveOptions} from "../repository/RemoveOptions"; +import {SaveOptions} from "../repository/SaveOptions"; +import {MongoRepository} from "../repository/MongoRepository"; +import {TreeRepository} from "../repository/TreeRepository"; +import {Repository} from "../repository/Repository"; +import {QueryRunner} from "../query-runner/QueryRunner"; +import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder"; +import {QueryDeepPartialEntity} from "../query-builder/QueryPartialEntity"; +import {ObjectID} from "../driver/mongodb/typings"; +import {InsertResult} from "../query-builder/result/InsertResult"; +import {UpdateResult} from "../query-builder/result/UpdateResult"; +import {DeleteResult} from "../query-builder/result/DeleteResult"; +import {IsolationLevel} from "../driver/types/IsolationLevel"; +import {FindExtraOptions, FindOptions, FindOptionsWhere} from "../find-options/FindOptions"; import * as Observable from "zen-observable"; -import { DeepPartial } from "../common/DeepPartial"; -import { EntityTarget } from "../common/EntityTarget"; -import { ObjectType } from "../common/ObjectType"; -import { Connection } from "../connection/Connection"; -import { ObjectID } from "../driver/mongodb/typings"; -import { IsolationLevel } from "../driver/types/IsolationLevel"; -import { FindExtraOptions, FindOptions, FindOptionsWhere } from "../find-options/FindOptions"; -import { QueryDeepPartialEntity } from "../query-builder/QueryPartialEntity"; -import { DeleteResult } from "../query-builder/result/DeleteResult"; -import { InsertResult } from "../query-builder/result/InsertResult"; -import { UpdateResult } from "../query-builder/result/UpdateResult"; -import { SelectQueryBuilder } from "../query-builder/SelectQueryBuilder"; -import { QueryRunner } from "../query-runner/QueryRunner"; -import { MongoRepository } from "../repository/MongoRepository"; -import { RemoveOptions } from "../repository/RemoveOptions"; -import { Repository } from "../repository/Repository"; -import { SaveOptions } from "../repository/SaveOptions"; -import { TreeRepository } from "../repository/TreeRepository"; -import { EntitySchema } from ".."; /** * Entity manager supposed to work with any entity, automatically find its repository and call its methods, @@ -90,7 +89,7 @@ export type EntityManager = { /** * Gets entity mixed id. */ - getId(target: Function|string, entity: any): any; + getId(target: EntityTarget, entity: any): any; /** * Creates a new entity instance and copies all entity properties from this object into a new entity. @@ -110,7 +109,7 @@ export type EntityManager = { merge(entityClass: EntityTarget, mergeIntoEntity: Entity, ...entityLikes: DeepPartial[]): Entity; /** - * Creates a new entity from the given plan javascript object. If entity already exist in the database, then + * Creates a new entity from the given plain javascript object. If entity already exist in the database, then * it loads it (and everything related to it), replaces all values with the new ones from the given object * and returns this new entity. This new entity is actually a loaded from the db entity with all properties * replaced from the new object. @@ -174,22 +173,12 @@ export type EntityManager = { /** * Records the delete date of all given entities. */ - softRemove>(targetOrEntity: ObjectType|EntitySchema, entities: T[], options?: SaveOptions): Promise; + softRemove>(targetOrEntity: EntityTarget, entities: T[], options?: SaveOptions): Promise; /** * Records the delete date of a given entity. */ - softRemove>(targetOrEntity: ObjectType|EntitySchema, entity: T, options?: SaveOptions): Promise; - - /** - * Records the delete date of all given entities. - */ - softRemove(targetOrEntity: string, entities: T[], options?: SaveOptions): Promise; - - /** - * Records the delete date of a given entity. - */ - softRemove(targetOrEntity: string, entity: T, options?: SaveOptions): Promise; + softRemove>(targetOrEntity: EntityTarget, entity: T, options?: SaveOptions): Promise; /** * Recovers all given entities. @@ -204,22 +193,12 @@ export type EntityManager = { /** * Recovers all given entities. */ - recover>(targetOrEntity: ObjectType|EntitySchema, entities: T[], options?: SaveOptions): Promise; - - /** - * Recovers a given entity. - */ - recover>(targetOrEntity: ObjectType|EntitySchema, entity: T, options?: SaveOptions): Promise; - - /** - * Recovers all given entities. - */ - recover(targetOrEntity: string, entities: T[], options?: SaveOptions): Promise; + recover>(targetOrEntity: EntityTarget, entities: T[], options?: SaveOptions): Promise; /** * Recovers a given entity. */ - recover(targetOrEntity: string, entity: T, options?: SaveOptions): Promise; + recover>(targetOrEntity: EntityTarget, entity: T, options?: SaveOptions): Promise; /** * Inserts a given entity into the database. @@ -255,7 +234,7 @@ export type EntityManager = { * Does not check if entity exist in the database. * Condition(s) cannot be empty. */ - softDelete(targetOrEntity: ObjectType | EntitySchema | string, criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | any): Promise; + softDelete(targetOrEntity: EntityTarget, criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | any): Promise; /** * Restores entities by a given condition(s). @@ -264,7 +243,7 @@ export type EntityManager = { * Does not check if entity exist in the database. * Condition(s) cannot be empty. */ - restore(targetOrEntity: ObjectType | EntitySchema | string, criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | any): Promise; + restore(targetOrEntity: EntityTarget, criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | any): Promise; /** * Counts entities that match given find options or conditions. diff --git a/src/entity-manager/EntityManagerFactory.ts b/src/entity-manager/EntityManagerFactory.ts index 110ad18965..c699a57006 100644 --- a/src/entity-manager/EntityManagerFactory.ts +++ b/src/entity-manager/EntityManagerFactory.ts @@ -1,11 +1,11 @@ -import { Connection } from "../connection/Connection"; -import { MongoDriver } from "../driver/mongodb/MongoDriver"; -import { SqljsDriver } from "../driver/sqljs/SqljsDriver"; -import { QueryRunner } from "../query-runner/QueryRunner"; -import { EntityManager } from "./EntityManager"; -import { createLiteralEntityManager } from "./LiteralEntityManager"; -import { createLiteralMongoEntityManager } from "./LiteralMongoEntityManager"; -import { createLiteralSqljsEntityManager } from "./LiteralSqljsEntityManager"; +import {Connection} from "../connection/Connection"; +import {EntityManager} from "./EntityManager"; +import {MongoDriver} from "../driver/mongodb/MongoDriver"; +import {SqljsDriver} from "../driver/sqljs/SqljsDriver"; +import {QueryRunner} from "../query-runner/QueryRunner"; +import {createLiteralEntityManager} from "./LiteralEntityManager"; +import {createLiteralMongoEntityManager} from "./LiteralMongoEntityManager"; +import {createLiteralSqljsEntityManager} from "./LiteralSqljsEntityManager"; /** * Helps to create entity managers. diff --git a/src/entity-manager/LiteralEntityManager.ts b/src/entity-manager/LiteralEntityManager.ts index 9671c193ae..0817aa47e2 100644 --- a/src/entity-manager/LiteralEntityManager.ts +++ b/src/entity-manager/LiteralEntityManager.ts @@ -42,7 +42,7 @@ import {createLiteralRepository} from "../repository/LiteralRepository"; * Entity manager supposed to work with any entity, automatically find its repository and call its methods, * whatever entity type are you passing. */ -export function createLiteralEntityManager({ connection, queryRunner }: { +export function createLiteralEntityManager({ connection, queryRunner }: { connection: Connection, queryRunner?: QueryRunner, }): EntityManager { @@ -90,7 +90,7 @@ export function createLiteralEntityManager({ connection, queryRunner }: // if query runner is already defined in this class, it means this entity manager was already created for a single connection // if its not defined we create a new query runner - single connection where we'll execute all our operations - const queryRunner = this.queryRunner || this.connection.createQueryRunner("master"); + const queryRunner = this.queryRunner || this.connection.createQueryRunner(); try { if (isolation) { @@ -534,10 +534,13 @@ export function createLiteralEntityManager({ connection, queryRunner }: return qb.getOne(); }, - async findOneOrFail(entityClass: EntityTarget, idOrOptionsOrConditions?: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindOptions | any, maybeOptions?: FindOptions): Promise { - return this.findOne(entityClass as any, idOrOptionsOrConditions as any, maybeOptions).then((value: any) => { + async findOneOrFail( + entityClass: EntityTarget, + ...args: (string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindOptions | any)[] + ): Promise { + return this.findOne(entityClass as any, ...args).then((value: any) => { if (value === undefined) { - return Promise.reject(new EntityNotFoundError(entityClass, idOrOptionsOrConditions)); + return Promise.reject(new EntityNotFoundError(entityClass, args.length > 0 ? args[0]: undefined)); } return Promise.resolve(value); }); @@ -565,7 +568,7 @@ export function createLiteralEntityManager({ connection, queryRunner }: async clear(entityClass: EntityTarget): Promise { const metadata = this.connection.getMetadata(entityClass); - const queryRunner = this.queryRunner || this.connection.createQueryRunner("master"); + const queryRunner = this.queryRunner || this.connection.createQueryRunner(); try { return await queryRunner.clearTable(metadata.tablePath); // await is needed here because we are using finally diff --git a/src/entity-manager/LiteralMongoEntityManager.ts b/src/entity-manager/LiteralMongoEntityManager.ts index ff33c87a4e..ec6ff09b13 100644 --- a/src/entity-manager/LiteralMongoEntityManager.ts +++ b/src/entity-manager/LiteralMongoEntityManager.ts @@ -57,7 +57,7 @@ import { createLiteralEntityManager } from "./LiteralEntityManager"; * * This implementation is used for MongoDB driver which has some specifics in its EntityManager. */ -export function createLiteralMongoEntityManager({ connection }: { +export function createLiteralMongoEntityManager({ connection }: { connection: Connection, }): MongoEntityManager { diff --git a/src/entity-manager/LiteralSqljsEntityManager.ts b/src/entity-manager/LiteralSqljsEntityManager.ts index bfa54590cd..54a63406ff 100644 --- a/src/entity-manager/LiteralSqljsEntityManager.ts +++ b/src/entity-manager/LiteralSqljsEntityManager.ts @@ -8,7 +8,7 @@ import { SqljsEntityManager } from "./SqljsEntityManager"; * A special EntityManager that includes import/export and load/save function * that are unique to Sql.js. */ -export function createLiteralSqljsEntityManager({ connection, queryRunner }: { +export function createLiteralSqljsEntityManager({ connection, queryRunner }: { connection: Connection, queryRunner?: QueryRunner, }): SqljsEntityManager { diff --git a/src/entity-manager/MongoEntityManager.ts b/src/entity-manager/MongoEntityManager.ts index af233f5caa..537d005ff9 100644 --- a/src/entity-manager/MongoEntityManager.ts +++ b/src/entity-manager/MongoEntityManager.ts @@ -1,5 +1,5 @@ -import { ObjectLiteral } from "../common/ObjectLiteral"; -import { MongoQueryRunner } from "../driver/mongodb/MongoQueryRunner"; +import { EntityManager } from "./EntityManager"; +import { EntityTarget } from "../common/EntityTarget"; import { AggregationCursor, BulkWriteOpResultObject, @@ -34,12 +34,13 @@ import { UpdateWriteOpResult } from "../driver/mongodb/typings"; import { FindOptions, FindOptionsWhere } from "../find-options/FindOptions"; -import { EntityTarget, FindExtraOptions } from "../index"; +import { FindExtraOptions } from "../index"; +import { ObjectLiteral } from "../common/ObjectLiteral"; +import { MongoQueryRunner } from "../driver/mongodb/MongoQueryRunner"; import { QueryDeepPartialEntity } from "../query-builder/QueryPartialEntity"; -import { DeleteResult } from "../query-builder/result/DeleteResult"; import { InsertResult } from "../query-builder/result/InsertResult"; import { UpdateResult } from "../query-builder/result/UpdateResult"; -import { EntityManager } from "./EntityManager"; +import { DeleteResult } from "../query-builder/result/DeleteResult"; /** * Entity manager supposed to work with any entity, automatically find its repository and call its methods, diff --git a/src/entity-manager/SqljsEntityManager.ts b/src/entity-manager/SqljsEntityManager.ts index 7ce3467f23..eae7359d61 100644 --- a/src/entity-manager/SqljsEntityManager.ts +++ b/src/entity-manager/SqljsEntityManager.ts @@ -1,4 +1,4 @@ -import { EntityManager } from "./EntityManager"; +import {EntityManager} from "./EntityManager"; /** * A special EntityManager that includes import/export and load/save function diff --git a/src/entity-schema/EntitySchemaRelationOptions.ts b/src/entity-schema/EntitySchemaRelationOptions.ts index 953caaccd6..0502fc67e6 100644 --- a/src/entity-schema/EntitySchemaRelationOptions.ts +++ b/src/entity-schema/EntitySchemaRelationOptions.ts @@ -55,7 +55,7 @@ export interface EntitySchemaRelationOptions { /** * Join column options of this column. If set to true then it simply means that it has a join column. */ - joinColumn?: boolean|JoinColumnOptions; + joinColumn?: boolean|JoinColumnOptions|JoinColumnOptions[]; /** * Indicates if this is a parent (can be only many-to-one relation) relation in the tree tables. diff --git a/src/entity-schema/EntitySchemaTransformer.ts b/src/entity-schema/EntitySchemaTransformer.ts index 3ec3667e5a..64c2de8e33 100644 --- a/src/entity-schema/EntitySchemaTransformer.ts +++ b/src/entity-schema/EntitySchemaTransformer.ts @@ -202,13 +202,17 @@ export class EntitySchemaTransformer { }; metadataArgsStorage.joinColumns.push(joinColumn); } else { - const joinColumn: JoinColumnMetadataArgs = { - target: options.target || optionsName, - propertyName: relationName, - name: relationSchema.joinColumn.name, - referencedColumnName: relationSchema.joinColumn.referencedColumnName - }; - metadataArgsStorage.joinColumns.push(joinColumn); + const joinColumnsOptions = Array.isArray(relationSchema.joinColumn) ? relationSchema.joinColumn : [relationSchema.joinColumn]; + + for (const joinColumnOption of joinColumnsOptions) { + const joinColumn: JoinColumnMetadataArgs = { + target: options.target || optionsName, + propertyName: relationName, + name: joinColumnOption.name, + referencedColumnName: joinColumnOption.referencedColumnName + }; + metadataArgsStorage.joinColumns.push(joinColumn); + } } } diff --git a/src/error/EntityMetadataNotFoundError.ts b/src/error/EntityMetadataNotFoundError.ts index a26d9bd613..26e6fa98f6 100644 --- a/src/error/EntityMetadataNotFoundError.ts +++ b/src/error/EntityMetadataNotFoundError.ts @@ -1,4 +1,5 @@ -import {EntitySchema, EntityTarget} from "../index"; +import {EntityTarget} from "../common/EntityTarget"; +import {EntitySchema} from "../index"; /** */ @@ -13,7 +14,7 @@ export class EntityMetadataNotFoundError extends Error { targetName = target.options.name || ""; } else if (typeof target === "function") { targetName = target.name; - } else if (typeof target === "object") { + } else if (typeof target === "object" && "name" in target) { targetName = target.name; } else { targetName = target; diff --git a/src/error/EntityNotFoundError.ts b/src/error/EntityNotFoundError.ts index 56d44f9764..593fceb065 100644 --- a/src/error/EntityNotFoundError.ts +++ b/src/error/EntityNotFoundError.ts @@ -1,4 +1,5 @@ -import {EntitySchema, EntityTarget} from "../index"; +import {EntityTarget} from "../common/EntityTarget"; +import {EntitySchema} from "../index"; /** * Thrown when no result could be found in methods which are not allowed to return undefined or an empty set. @@ -14,7 +15,7 @@ export class EntityNotFoundError extends Error { targetName = (entityClass as EntitySchema).options.name || ""; } else if (typeof entityClass === "function") { targetName = entityClass.name; - } else if (typeof entityClass === "object") { + } else if (typeof entityClass === "object" && "name" in entityClass) { targetName = entityClass.name; } else { targetName = entityClass; diff --git a/src/error/FindCriteriaNotFoundError.ts b/src/error/FindCriteriaNotFoundError.ts index 1b0f5032c8..e3c535cd74 100644 --- a/src/error/FindCriteriaNotFoundError.ts +++ b/src/error/FindCriteriaNotFoundError.ts @@ -1,14 +1,15 @@ import {EntityMetadata} from ".."; +import {EntityColumnNotFound} from "./EntityColumnNotFound"; /** * Thrown when specified entity property in the find options were not found. */ -export class FindCriteriaNotFoundError extends Error { +export class FindCriteriaNotFoundError extends EntityColumnNotFound { constructor(propertyPath: string, metadata: EntityMetadata) { - super(); + super(propertyPath); Object.setPrototypeOf(this, FindCriteriaNotFoundError.prototype); this.message = `Property "${propertyPath}" was not found in ${metadata.targetName}. Make sure your query is correct.`; } -} \ No newline at end of file +} diff --git a/src/error/MissingDriverError.ts b/src/error/MissingDriverError.ts index 01abd5492c..5d2518fb55 100644 --- a/src/error/MissingDriverError.ts +++ b/src/error/MissingDriverError.ts @@ -7,7 +7,7 @@ export class MissingDriverError extends Error { constructor(driverType: string) { super(); Object.setPrototypeOf(this, MissingDriverError.prototype); - this.message = `Wrong driver: "${driverType}" given. Supported drivers are: "cordova", "expo", "mariadb", "mongodb", "mssql", "mysql", "oracle", "postgres", "sqlite", "sqljs", "react-native".`; + this.message = `Wrong driver: "${driverType}" given. Supported drivers are: "cordova", "expo", "mariadb", "mongodb", "mssql", "mysql", "oracle", "postgres", "sqlite", "better-sqlite3", "sqljs", "react-native", "aurora-data-api", "aurora-data-api-pg".`; } -} \ No newline at end of file +} diff --git a/src/error/RepositoryNotFoundError.ts b/src/error/RepositoryNotFoundError.ts index 6171628f3d..488b323124 100644 --- a/src/error/RepositoryNotFoundError.ts +++ b/src/error/RepositoryNotFoundError.ts @@ -1,3 +1,4 @@ +import {EntityTarget} from "../common/EntityTarget"; import {EntitySchema} from "../index"; /** @@ -6,7 +7,7 @@ import {EntitySchema} from "../index"; export class RepositoryNotFoundError extends Error { name = "RepositoryNotFoundError"; - constructor(connectionName: string, entityClass: Function|EntitySchema|string) { + constructor(connectionName: string, entityClass: EntityTarget) { super(); Object.setPrototypeOf(this, RepositoryNotFoundError.prototype); let targetName: string; @@ -14,6 +15,8 @@ export class RepositoryNotFoundError extends Error { targetName = (entityClass as EntitySchema).options.name || ""; } else if (typeof entityClass === "function") { targetName = entityClass.name; + } else if (typeof entityClass === "object" && "name" in entityClass) { + targetName = entityClass.name; } else { targetName = entityClass; } diff --git a/src/error/RepositoryNotTreeError.ts b/src/error/RepositoryNotTreeError.ts index fc4ae16da4..ecf82058ba 100644 --- a/src/error/RepositoryNotTreeError.ts +++ b/src/error/RepositoryNotTreeError.ts @@ -1,3 +1,4 @@ +import {EntityTarget} from "../common/EntityTarget"; import {EntitySchema} from "../index"; /** @@ -6,16 +7,18 @@ import {EntitySchema} from "../index"; export class RepositoryNotTreeError extends Error { name = "RepositoryNotTreeError"; - constructor(target: Function|EntitySchema|string) { + constructor(entityClass: EntityTarget) { super(); Object.setPrototypeOf(this, RepositoryNotTreeError.prototype); let targetName: string; - if (target instanceof EntitySchema) { - targetName = target.options.name || ""; - } else if (typeof target === "function") { - targetName = target.name; + if (entityClass instanceof EntitySchema) { + targetName = entityClass.options.name || ""; + } else if (typeof entityClass === "function") { + targetName = entityClass.name; + } else if (typeof entityClass === "object" && "name" in entityClass) { + targetName = entityClass.name; } else { - targetName = target; + targetName = entityClass; } this.message = `Repository of the "${targetName}" class is not a TreeRepository. Try to apply @Tree decorator on your entity.`; } diff --git a/src/find-options/FindOperator.ts b/src/find-options/FindOperator.ts index b3b772b311..05e68a4dd7 100644 --- a/src/find-options/FindOperator.ts +++ b/src/find-options/FindOperator.ts @@ -1,5 +1,7 @@ import {FindOperatorType} from "./FindOperatorType"; import {Connection} from "../"; +import {OracleDriver} from "../driver/oracle/OracleDriver"; +import {MysqlDriver} from "../driver/mysql/MysqlDriver"; /** * Find Operator used in Find Conditions. @@ -38,14 +40,11 @@ export class FindOperator { // Constructor // ------------------------------------------------------------------------- - constructor(type: FindOperatorType, - value: T|FindOperator, - useParameter: boolean = true, - multipleParameters: boolean = false) { + constructor(type: FindOperatorType, value: T|FindOperator, useParameter: boolean = true, multipleParameters: boolean = false) { this.type = type; + this._value = value; this._useParameter = useParameter; this._multipleParameters = multipleParameters; - this._value = value; // if (condition !== undefined) { // this.condition = condition; // this._useParameter = condition === true ? true : false; @@ -120,6 +119,9 @@ export class FindOperator { case "between": return `${aliasPath} BETWEEN ${parameters[0]} AND ${parameters[1]}`; case "in": + if ((connection.driver instanceof OracleDriver || connection.driver instanceof MysqlDriver) && parameters.length === 0) { + return `${aliasPath} IN (null)`; + } return `${aliasPath} IN (${parameters.join(", ")})`; case "any": return `${aliasPath} = ANY(${parameters[0]})`; @@ -136,4 +138,4 @@ export class FindOperator { return ""; } -} \ No newline at end of file +} diff --git a/src/find-options/FindOperatorType.ts b/src/find-options/FindOperatorType.ts index a8c00ecd9b..fabccdff9a 100644 --- a/src/find-options/FindOperatorType.ts +++ b/src/find-options/FindOperatorType.ts @@ -1,8 +1,7 @@ /** * List of types that FindOperator can be. */ -export type FindOperatorType = - | "not" +export type FindOperatorType = "not" | "lessThan" | "lessThanOrEqual" | "moreThan" @@ -14,6 +13,6 @@ export type FindOperatorType = | "isNull" | "like" | "ilike" - | "raw" | "if" - | "switch"; + | "switch" + | "raw"; diff --git a/src/find-options/FindOptionsUtils.ts b/src/find-options/FindOptionsUtils.ts index 942c2a2f11..66827ca57f 100644 --- a/src/find-options/FindOptionsUtils.ts +++ b/src/find-options/FindOptionsUtils.ts @@ -88,30 +88,33 @@ export function normalizeFindOptions(options: FindOptions): FindOptions const recursivelyWhere = (where: T): T => { - if ((where as any) instanceof Array) - return where.map((where: any) => recursivelyWhere(where)); + if (Array.isArray(where)) { + return where.map((where: any) => recursivelyWhere(where)) as T; + } + + return Object.keys(where as { [key: string ]: any }).reduce((newWhere, key) => { + const value = (where as { [key: string]: any })[key]; - return Object.keys(where).reduce((newWhere, key) => { - if (where[key] instanceof Object && !(where[key] instanceof FindOperator)) { - newWhere[key] = recursively$FindOption(where[key]); + if (value instanceof Object && !(value instanceof FindOperator)) { + newWhere[key] = recursively$FindOption(value); // in the case if $find operator was not found we'll have a false as a value // we need to recursive where because it can be another where options if (newWhere[key] === false) - newWhere[key] = recursivelyWhere(where[key]); + newWhere[key] = recursivelyWhere(value); } else { - newWhere[key] = where[key]; + newWhere[key] = value; } return newWhere; - }, {} as T); + }, {} as { [key: string]: any }) as T; }; // todo: broken after merge // if (options.lock) { // if (options.lock.mode === "optimistic") { // qb.setLock(options.lock.mode, options.lock.version as any); - // } else if (options.lock.mode === "pessimistic_read" || options.lock.mode === "pessimistic_write") { + // } else if (options.lock.mode === "pessimistic_read" || options.lock.mode === "pessimistic_write" || options.lock.mode === "dirty_read" || options.lock.mode === "pessimistic_partial_write" || options.lock.mode === "pessimistic_write_or_fail") { // qb.setLock(options.lock.mode); // } // } diff --git a/src/find-options/operator/Raw.ts b/src/find-options/operator/Raw.ts index 41fddb7620..ff8d4fd811 100644 --- a/src/find-options/operator/Raw.ts +++ b/src/find-options/operator/Raw.ts @@ -6,4 +6,4 @@ import {FindOperator} from "../FindOperator"; */ export function Raw(value: string|((columnAlias?: string) => string)): FindOperator { return new FindOperator("raw", value as any, false); -} \ No newline at end of file +} diff --git a/src/index.ts b/src/index.ts index 9e22d5b61f..342d8ac5f9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,7 +14,6 @@ import {PlatformTools} from "./platform/PlatformTools"; import {TreeRepository} from "./repository/TreeRepository"; import {MongoRepository} from "./repository/MongoRepository"; import {ConnectionOptionsReader} from "./connection/ConnectionOptionsReader"; -import {PromiseUtils} from "./util/PromiseUtils"; import {MongoEntityManager} from "./entity-manager/MongoEntityManager"; import {SqljsEntityManager} from "./entity-manager/SqljsEntityManager"; import {SelectQueryBuilder} from "./query-builder/SelectQueryBuilder"; @@ -25,8 +24,8 @@ import {EntityTarget} from "./common/EntityTarget"; // ------------------------------------------------------------------------- export * from "./container"; -export * from "./common/ObjectType"; export * from "./common/EntityTarget"; +export * from "./common/ObjectType"; export * from "./common/ObjectLiteral"; export * from "./common/DeepPartial"; export * from "./error/QueryFailedError"; @@ -117,6 +116,7 @@ export * from "./schema-builder/table/TableUnique"; export * from "./schema-builder/table/Table"; export * from "./driver/mongodb/typings"; export * from "./driver/types/DatabaseType"; +export * from "./driver/types/ReplicationMode"; export * from "./driver/sqlserver/MssqlParameter"; export * from "./typed-entity-schema"; @@ -139,7 +139,6 @@ export {DeleteResult} from "./query-builder/result/DeleteResult"; export {QueryPartialEntity} from "./query-builder/QueryPartialEntity"; export {QueryDeepPartialEntity} from "./query-builder/QueryPartialEntity"; export {QueryRunner} from "./query-runner/QueryRunner"; -export {EntityManager} from "./entity-manager/EntityManager"; export {MongoEntityManager} from "./entity-manager/MongoEntityManager"; export {Migration} from "./migration/Migration"; export {MigrationExecutor} from "./migration/MigrationExecutor"; @@ -153,16 +152,15 @@ export {TreeRepository} from "./repository/TreeRepository"; export {MongoRepository} from "./repository/MongoRepository"; export * from "./find-options/FindOptions"; export {InsertEvent} from "./subscriber/event/InsertEvent"; +export {LoadEvent} from "./subscriber/event/LoadEvent"; export {UpdateEvent} from "./subscriber/event/UpdateEvent"; export {RemoveEvent} from "./subscriber/event/RemoveEvent"; export {EntitySubscriberInterface} from "./subscriber/EntitySubscriberInterface"; -export {BaseEntity} from "./repository/BaseEntity"; export {EntitySchema} from "./entity-schema/EntitySchema"; export {EntitySchemaColumnOptions} from "./entity-schema/EntitySchemaColumnOptions"; export {EntitySchemaIndexOptions} from "./entity-schema/EntitySchemaIndexOptions"; export {EntitySchemaRelationOptions} from "./entity-schema/EntitySchemaRelationOptions"; export {ColumnType} from "./driver/types/ColumnTypes"; -export {PromiseUtils} from "./util/PromiseUtils"; // ------------------------------------------------------------------------- // Deprecated @@ -245,7 +243,7 @@ export async function createConnections(options?: ConnectionOptions[]): Promise< if (!options) options = await new ConnectionOptionsReader().all(); const connections = options.map(options => getConnectionManager().create(options)); - return PromiseUtils.runInSequence(connections, connection => connection.connect()); + return Promise.all(connections.map(connection => connection.connect())); } /** diff --git a/src/logger/DebugLogger.ts b/src/logger/DebugLogger.ts index 8943a4523b..36e901187a 100644 --- a/src/logger/DebugLogger.ts +++ b/src/logger/DebugLogger.ts @@ -1,3 +1,4 @@ +import debug from "debug"; import {Logger} from "./Logger"; import {QueryRunner} from "../"; import {PlatformTools} from "../platform/PlatformTools"; @@ -6,18 +7,16 @@ import {PlatformTools} from "../platform/PlatformTools"; * Performs logging of the events in TypeORM via debug library. */ export class DebugLogger implements Logger { - private debug = PlatformTools.load("debug"); + private debugQueryLog = debug("typeorm:query:log"); + private debugQueryError = debug("typeorm:query:error"); + private debugQuerySlow = debug("typeorm:query:slow"); + private debugSchemaBuild = debug("typeorm:schema"); + private debugMigration = debug("typeorm:migration"); + + private debugLog = debug("typeorm:log"); + private debugInfo = debug("typeorm:info"); + private debugWarn = debug("typeorm:warn"); - private debugQueryLog = this.debug("typeorm:query:log"); - private debugQueryError = this.debug("typeorm:query:error"); - private debugQuerySlow = this.debug("typeorm:query:slow"); - private debugSchemaBuild = this.debug("typeorm:schema"); - private debugMigration = this.debug("typeorm:migration"); - - private debugLog = this.debug("typeorm:log"); - private debugInfo = this.debug("typeorm:info"); - private debugWarn = this.debug("typeorm:warn"); - /** * Logs query and parameters used in it. */ @@ -29,7 +28,7 @@ export class DebugLogger implements Logger { } } } - + /** * Logs query that failed. */ @@ -42,7 +41,7 @@ export class DebugLogger implements Logger { this.debugQueryError("error: ", error); } } - + /** * Logs query that is slow. */ @@ -55,7 +54,7 @@ export class DebugLogger implements Logger { this.debugQuerySlow("execution time:", time); } } - + /** * Logs events from the schema build process. */ @@ -64,7 +63,7 @@ export class DebugLogger implements Logger { this.debugSchemaBuild(message); } } - + /** * Logs events from the migration run process. */ @@ -73,7 +72,7 @@ export class DebugLogger implements Logger { this.debugMigration(message); } } - + /** * Perform logging using given logger. * Log has its own level and message. diff --git a/src/logger/FileLogger.ts b/src/logger/FileLogger.ts index 3bdccda7bd..e96d142ad2 100644 --- a/src/logger/FileLogger.ts +++ b/src/logger/FileLogger.ts @@ -1,4 +1,5 @@ -import {LoggerOptions} from "./LoggerOptions"; +import {LoggerOptions, FileLoggerOptions} from "./LoggerOptions"; +import appRootPath from "app-root-path"; import {QueryRunner} from "../query-runner/QueryRunner"; import {Logger} from "./Logger"; import {PlatformTools} from "../platform/PlatformTools"; @@ -13,7 +14,10 @@ export class FileLogger implements Logger { // Constructor // ------------------------------------------------------------------------- - constructor(private options?: LoggerOptions) { + constructor( + private options?: LoggerOptions, + private fileLoggerOptions?: FileLoggerOptions, + ) { } // ------------------------------------------------------------------------- @@ -97,9 +101,13 @@ export class FileLogger implements Logger { */ protected write(strings: string|string[]) { strings = Array.isArray(strings) ? strings : [strings]; - const basePath = PlatformTools.load("app-root-path").path; + const basePath = appRootPath.path + "/"; + let logPath = "ormlogs.log"; + if (this.fileLoggerOptions && this.fileLoggerOptions.logPath) { + logPath = PlatformTools.pathNormalize(this.fileLoggerOptions.logPath); + } strings = (strings as string[]).map(str => "[" + new Date().toISOString() + "]" + str); - PlatformTools.appendFileSync(basePath + "/ormlogs.log", strings.join("\r\n") + "\r\n"); // todo: use async or implement promises? + PlatformTools.appendFileSync(basePath + logPath, strings.join("\r\n") + "\r\n"); // todo: use async or implement promises? } /** diff --git a/src/logger/LoggerOptions.ts b/src/logger/LoggerOptions.ts index 67049d5a4f..adfff93488 100644 --- a/src/logger/LoggerOptions.ts +++ b/src/logger/LoggerOptions.ts @@ -2,3 +2,13 @@ * Logging options. */ export type LoggerOptions = boolean|"all"|("query"|"schema"|"error"|"warn"|"info"|"log"|"migration")[]; + +/** + * File logging option. + */ +export type FileLoggerOptions = { + /** + * Specify custom path for log file, relative to application root + */ + logPath: string; +}; diff --git a/src/metadata-args/EntityRepositoryMetadataArgs.ts b/src/metadata-args/EntityRepositoryMetadataArgs.ts index 3e7373003c..fd55676630 100644 --- a/src/metadata-args/EntityRepositoryMetadataArgs.ts +++ b/src/metadata-args/EntityRepositoryMetadataArgs.ts @@ -1,4 +1,4 @@ -import {EntitySchema} from "../entity-schema/EntitySchema"; +import { EntityTarget } from "../common/EntityTarget"; /** * Arguments for EntityRepositoryMetadata class, helps to construct an EntityRepositoryMetadata object. @@ -13,6 +13,6 @@ export interface EntityRepositoryMetadataArgs { /** * Entity managed by this custom repository. */ - readonly entity?: Function|string|EntitySchema; + readonly entity?: EntityTarget; } diff --git a/src/metadata-builder/EntityMetadataBuilder.ts b/src/metadata-builder/EntityMetadataBuilder.ts index 34030b2d2a..bc93c5fc5e 100644 --- a/src/metadata-builder/EntityMetadataBuilder.ts +++ b/src/metadata-builder/EntityMetadataBuilder.ts @@ -403,6 +403,8 @@ export class EntityMetadataBuilder { } } + const { namingStrategy } = this.connection; + // check if tree is used then we need to add extra columns for specific tree types if (entityMetadata.treeType === "materialized-path") { entityMetadata.ownColumns.push(new ColumnMetadata({ @@ -414,7 +416,7 @@ export class EntityMetadataBuilder { mode: "virtual", propertyName: "mpath", options: /*tree.column || */ { - name: "mpath", + name: namingStrategy.materializedPathColumnName, type: "varchar", nullable: true, default: "" @@ -423,6 +425,7 @@ export class EntityMetadataBuilder { })); } else if (entityMetadata.treeType === "nested-set") { + const { left, right } = namingStrategy.nestedSetColumnNames; entityMetadata.ownColumns.push(new ColumnMetadata({ connection: this.connection, entityMetadata: entityMetadata, @@ -430,9 +433,9 @@ export class EntityMetadataBuilder { args: { target: entityMetadata.target, mode: "virtual", - propertyName: "nsleft", + propertyName: left, options: /*tree.column || */ { - name: "nsleft", + name: left, type: "integer", nullable: false, default: 1 @@ -446,9 +449,9 @@ export class EntityMetadataBuilder { args: { target: entityMetadata.target, mode: "virtual", - propertyName: "nsright", + propertyName: right, options: /*tree.column || */ { - name: "nsright", + name: right, type: "integer", nullable: false, default: 2 diff --git a/src/metadata-builder/JunctionEntityMetadataBuilder.ts b/src/metadata-builder/JunctionEntityMetadataBuilder.ts index 079559fcaf..9fbb1ed733 100644 --- a/src/metadata-builder/JunctionEntityMetadataBuilder.ts +++ b/src/metadata-builder/JunctionEntityMetadataBuilder.ts @@ -6,7 +6,7 @@ import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata"; import {IndexMetadata} from "../metadata/IndexMetadata"; import {JoinTableMetadataArgs} from "../metadata-args/JoinTableMetadataArgs"; import {RelationMetadata} from "../metadata/RelationMetadata"; -import { AuroraDataApiDriver } from "../driver/aurora-data-api/AuroraDataApiDriver"; +import {AuroraDataApiDriver} from "../driver/aurora-data-api/AuroraDataApiDriver"; /** * Creates EntityMetadata for junction tables. @@ -113,6 +113,7 @@ export class JunctionEntityMetadataBuilder { && (inverseReferencedColumn.generationStrategy === "uuid" || inverseReferencedColumn.type === "uuid") ? "36" : inverseReferencedColumn.length, // fix https://github.com/typeorm/typeorm/issues/3604 + width: inverseReferencedColumn.width, // fix https://github.com/typeorm/typeorm/issues/6442 type: inverseReferencedColumn.type, precision: inverseReferencedColumn.precision, scale: inverseReferencedColumn.scale, diff --git a/src/metadata/ColumnMetadata.ts b/src/metadata/ColumnMetadata.ts index f228133c5d..048eb1d2ed 100644 --- a/src/metadata/ColumnMetadata.ts +++ b/src/metadata/ColumnMetadata.ts @@ -7,7 +7,6 @@ import {ColumnMetadataArgs} from "../metadata-args/ColumnMetadataArgs"; import {Connection} from "../connection/Connection"; import {ValueTransformer} from "../decorator/options/ValueTransformer"; import {MongoDriver} from "../driver/mongodb/MongoDriver"; -import {PromiseUtils} from "../util/PromiseUtils"; import {FindOperator} from "../find-options/FindOperator"; import {ApplyValueTransformers} from "../util/ApplyValueTransformers"; @@ -579,21 +578,21 @@ export class ColumnMetadata { if (this.relationMetadata && this.referencedColumn) { const relatedEntity = this.relationMetadata.getEntityValue(embeddedObject); if (relatedEntity && relatedEntity instanceof Object && !(relatedEntity instanceof FindOperator)) { - value = this.referencedColumn.getEntityValue(PromiseUtils.extractValue(relatedEntity)); + value = this.referencedColumn.getEntityValue(relatedEntity); } else if (embeddedObject[this.propertyName] && embeddedObject[this.propertyName] instanceof Object && !(embeddedObject[this.propertyName] instanceof FindOperator)) { - value = this.referencedColumn.getEntityValue(PromiseUtils.extractValue(embeddedObject[this.propertyName])); + value = this.referencedColumn.getEntityValue(embeddedObject[this.propertyName]); } else { - value = PromiseUtils.extractValue(embeddedObject[this.propertyName]); + value = embeddedObject[this.propertyName]; } } else if (this.referencedColumn) { - value = this.referencedColumn.getEntityValue(PromiseUtils.extractValue(embeddedObject[this.propertyName])); + value = this.referencedColumn.getEntityValue(embeddedObject[this.propertyName]); } else { - value = PromiseUtils.extractValue(embeddedObject[this.propertyName]); + value = embeddedObject[this.propertyName]; } } @@ -601,17 +600,17 @@ export class ColumnMetadata { if (this.relationMetadata && this.referencedColumn) { const relatedEntity = this.relationMetadata.getEntityValue(entity); if (relatedEntity && relatedEntity instanceof Object && !(relatedEntity instanceof FindOperator) && !(relatedEntity instanceof Function)) { - value = this.referencedColumn.getEntityValue(PromiseUtils.extractValue(relatedEntity)); + value = this.referencedColumn.getEntityValue(relatedEntity); } else if (entity[this.propertyName] && entity[this.propertyName] instanceof Object && !(entity[this.propertyName] instanceof FindOperator) && !(entity[this.propertyName] instanceof Function)) { - value = this.referencedColumn.getEntityValue(PromiseUtils.extractValue(entity[this.propertyName])); + value = this.referencedColumn.getEntityValue(entity[this.propertyName]); } else { value = entity[this.propertyName]; } } else if (this.referencedColumn) { - value = this.referencedColumn.getEntityValue(PromiseUtils.extractValue(entity[this.propertyName])); + value = this.referencedColumn.getEntityValue(entity[this.propertyName]); } else { value = entity[this.propertyName]; diff --git a/src/metadata/EntityMetadata.ts b/src/metadata/EntityMetadata.ts index 044000d214..8fd085d8be 100644 --- a/src/metadata/EntityMetadata.ts +++ b/src/metadata/EntityMetadata.ts @@ -6,6 +6,7 @@ import {PostgresDriver} from "../driver/postgres/PostgresDriver"; import {SapDriver} from "../driver/sap/SapDriver"; import {SqlServerConnectionOptions} from "../driver/sqlserver/SqlServerConnectionOptions"; import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver"; +import {OracleDriver} from "../driver/oracle/OracleDriver"; import {CannotCreateEntityIdMapError} from "../error/CannotCreateEntityIdMapError"; import {OrderByCondition} from "../find-options/OrderByCondition"; import {TableMetadataArgs} from "../metadata-args/TableMetadataArgs"; @@ -630,7 +631,7 @@ export class EntityMetadata { const secondEntityIdMap = this.getEntityIdMap(secondEntity); if (!secondEntityIdMap) return false; - return EntityMetadata.compareIds(firstEntityIdMap, secondEntityIdMap); + return OrmUtils.compareIds(firstEntityIdMap, secondEntityIdMap); } /** @@ -720,14 +721,21 @@ export class EntityMetadata { relations.forEach(relation => { const value = relation.getEntityValue(entity); if (Array.isArray(value)) { - value.forEach(subValue => relationsAndValues.push([relation, subValue, relation.inverseEntityMetadata])); + value.forEach(subValue => relationsAndValues.push([relation, subValue, this.getInverseEntityMetadata(subValue, relation)])); } else if (value) { - relationsAndValues.push([relation, value, relation.inverseEntityMetadata]); + relationsAndValues.push([relation, value, this.getInverseEntityMetadata(value, relation)]); } }); return relationsAndValues; } + private getInverseEntityMetadata(value: any, relation: RelationMetadata): EntityMetadata { + const childEntityMetadata = relation.inverseEntityMetadata.childEntityMetadatas.find(metadata => + metadata.target === value.constructor + ); + return childEntityMetadata ? childEntityMetadata : relation.inverseEntityMetadata; + } + // ------------------------------------------------------------------------- // Public Static Methods // ------------------------------------------------------------------------- @@ -759,21 +767,10 @@ export class EntityMetadata { */ static difference(firstIdMaps: ObjectLiteral[], secondIdMaps: ObjectLiteral[]): ObjectLiteral[] { return firstIdMaps.filter(firstIdMap => { - return !secondIdMaps.find(secondIdMap => OrmUtils.deepCompare(firstIdMap, secondIdMap)); + return !secondIdMaps.find(secondIdMap => OrmUtils.compareIds(firstIdMap, secondIdMap)); }); } - /** - * Compares ids of the two entities. - * Returns true if they match, false otherwise. - */ - static compareIds(firstId: ObjectLiteral|undefined, secondId: ObjectLiteral|undefined): boolean { - if (firstId === undefined || firstId === null || secondId === undefined || secondId === null) - return false; - - return OrmUtils.deepCompare(firstId, secondId); - } - /** * Creates value map from the given values and columns. * Examples of usages are primary columns map and join columns map. @@ -872,7 +869,7 @@ export class EntityMetadata { */ protected buildTablePath(): string { let tablePath = this.tableName; - if (this.schema && ((this.connection.driver instanceof PostgresDriver) || (this.connection.driver instanceof SqlServerDriver) || (this.connection.driver instanceof SapDriver))) { + if (this.schema && ((this.connection.driver instanceof OracleDriver) || (this.connection.driver instanceof PostgresDriver) || (this.connection.driver instanceof SqlServerDriver) || (this.connection.driver instanceof SapDriver))) { tablePath = this.schema + "." + tablePath; } diff --git a/src/migration/MigrationExecutor.ts b/src/migration/MigrationExecutor.ts index 46754ed422..3ec3875039 100644 --- a/src/migration/MigrationExecutor.ts +++ b/src/migration/MigrationExecutor.ts @@ -2,7 +2,6 @@ import {Table} from "../schema-builder/table/Table"; import {Connection} from "../connection/Connection"; import {Migration} from "./Migration"; import {ObjectLiteral} from "../common/ObjectLiteral"; -import {PromiseUtils} from "../util/PromiseUtils"; import {QueryRunner} from "../query-runner/QueryRunner"; import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver"; import {MssqlParameter} from "../driver/sqlserver/MssqlParameter"; @@ -90,7 +89,7 @@ export class MigrationExecutor { const executedMigrations = await this.getExecutedMigrations(); return allMigrations.filter(migration => - executedMigrations.find( + !executedMigrations.find( executedMigration => executedMigration.name === migration.name ) @@ -129,7 +128,7 @@ export class MigrationExecutor { */ async showMigrations(): Promise { let hasUnappliedMigrations = false; - const queryRunner = this.queryRunner || this.connection.createQueryRunner("master"); + const queryRunner = this.queryRunner || this.connection.createQueryRunner(); // create migrations table if its not created yet await this.createMigrationsTableIfNotExist(queryRunner); // get all migrations that are executed and saved in the database @@ -163,7 +162,7 @@ export class MigrationExecutor { */ async executePendingMigrations(): Promise { - const queryRunner = this.queryRunner || this.connection.createQueryRunner("master"); + const queryRunner = this.queryRunner || this.connection.createQueryRunner(); // create migrations table if its not created yet await this.createMigrationsTableIfNotExist(queryRunner); // get all migrations that are executed and saved in the database @@ -218,13 +217,13 @@ export class MigrationExecutor { // run all pending migrations in a sequence try { - await PromiseUtils.runInSequence(pendingMigrations, async migration => { + for (const migration of pendingMigrations) { if (this.transaction === "each" && !queryRunner.isTransactionActive) { await queryRunner.startTransaction(); transactionStartedByUs = true; } - return migration.instance!.up(queryRunner) + await migration.instance!.up(queryRunner) .then(async () => { // now when migration is executed we need to insert record about it into the database await this.insertExecutedMigration(queryRunner, migration); // commit transaction if we started it @@ -235,7 +234,7 @@ export class MigrationExecutor { successMigrations.push(migration); this.connection.logger.logSchemaBuild(`Migration ${migration.name} has been executed successfully.`); }); - }); + } // commit transaction if we started it if (this.transaction === "all" && transactionStartedByUs) @@ -265,7 +264,7 @@ export class MigrationExecutor { */ async undoLastMigration(): Promise { - const queryRunner = this.queryRunner || this.connection.createQueryRunner("master"); + const queryRunner = this.queryRunner || this.connection.createQueryRunner(); // create migrations table if its not created yet await this.createMigrationsTableIfNotExist(queryRunner); @@ -496,7 +495,7 @@ export class MigrationExecutor { } protected async withQueryRunner(callback: (queryRunner: QueryRunner) => T) { - const queryRunner = this.queryRunner || this.connection.createQueryRunner("master"); + const queryRunner = this.queryRunner || this.connection.createQueryRunner(); try { return callback(queryRunner); diff --git a/src/naming-strategy/DefaultNamingStrategy.ts b/src/naming-strategy/DefaultNamingStrategy.ts index cbd08e71da..e34dd792a7 100644 --- a/src/naming-strategy/DefaultNamingStrategy.ts +++ b/src/naming-strategy/DefaultNamingStrategy.ts @@ -153,4 +153,7 @@ export class DefaultNamingStrategy implements NamingStrategyInterface { eagerJoinRelationAlias(alias: string, propertyPath: string): string { return alias + "_" + propertyPath.replace(".", "_"); } + + nestedSetColumnNames = { left: "nsleft", right: "nsright" }; + materializedPathColumnName = "mpath"; } diff --git a/src/naming-strategy/NamingStrategyInterface.ts b/src/naming-strategy/NamingStrategyInterface.ts index 72fd26ecd2..50342d32b1 100644 --- a/src/naming-strategy/NamingStrategyInterface.ts +++ b/src/naming-strategy/NamingStrategyInterface.ts @@ -121,4 +121,14 @@ export interface NamingStrategyInterface { * Gets the name of the alias used for relation joins. */ eagerJoinRelationAlias(alias: string, propertyPath: string): string; - } + + /** + * Column names for nested sets. + */ + nestedSetColumnNames: { left: string, right: string }; + + /** + * Column name for materialized paths. + */ + materializedPathColumnName: string; +} diff --git a/src/observer/QueryObserver.ts b/src/observer/QueryObserver.ts index 978d758607..43d3e95d98 100644 --- a/src/observer/QueryObserver.ts +++ b/src/observer/QueryObserver.ts @@ -9,7 +9,7 @@ import { UpdateEvent, EntityTarget } from "../index"; -import * as Observable from "zen-observable"; +import Observable from "zen-observable"; // todo: we probably need operation-level subscribers // todo: right now if we save 1000 entities within a single save call its going to call this code 1000 times diff --git a/src/persistence/EntityPersistExecutor.ts b/src/persistence/EntityPersistExecutor.ts index cd12513cc2..66f04d816b 100644 --- a/src/persistence/EntityPersistExecutor.ts +++ b/src/persistence/EntityPersistExecutor.ts @@ -14,7 +14,6 @@ import {ManyToManySubjectBuilder} from "./subject-builder/ManyToManySubjectBuild import {SubjectDatabaseEntityLoader} from "./SubjectDatabaseEntityLoader"; import {CascadesSubjectBuilder} from "./subject-builder/CascadesSubjectBuilder"; import {OrmUtils} from "../util/OrmUtils"; -import {PromiseUtils} from "../util/PromiseUtils"; /** * Persists a single entity or multiple entities - saves or removes them. @@ -51,7 +50,7 @@ export class EntityPersistExecutor { // if query runner is already defined in this class, it means this entity manager was already created for a single connection // if its not defined we create a new query runner - single connection where we'll execute all our operations - const queryRunner = this.queryRunner || this.connection.createQueryRunner("master"); + const queryRunner = this.queryRunner || this.connection.createQueryRunner(); // save data in the query runner - this is useful functionality to share data from outside of the world // with third classes - like subscribers and listener methods @@ -146,7 +145,9 @@ export class EntityPersistExecutor { // execute all persistence operations for all entities we have // console.time("executing subject executors..."); - await PromiseUtils.runInSequence(executorsWithExecutableOperations, executor => executor.execute()); + for (const executor of executorsWithExecutableOperations) { + await executor.execute(); + } // console.timeEnd("executing subject executors..."); // commit transaction if it was started by us diff --git a/src/persistence/SubjectChangedColumnsComputer.ts b/src/persistence/SubjectChangedColumnsComputer.ts index cddd575ad5..c510d3b211 100644 --- a/src/persistence/SubjectChangedColumnsComputer.ts +++ b/src/persistence/SubjectChangedColumnsComputer.ts @@ -1,8 +1,8 @@ import {Subject} from "./Subject"; import {DateUtils} from "../util/DateUtils"; import {ObjectLiteral} from "../common/ObjectLiteral"; -import {EntityMetadata} from "../metadata/EntityMetadata"; import {OrmUtils} from "../util/OrmUtils"; +import {ApplyValueTransformers} from "../util/ApplyValueTransformers"; /** * Finds what columns are changed in the subject entities. @@ -40,10 +40,11 @@ export class SubjectChangedColumnsComputer { // ignore special columns if (column.isVirtual || - column.isDiscriminator || - column.isUpdateDate || - column.isVersion || - column.isCreateDate) + column.isDiscriminator // || + // column.isUpdateDate || + // column.isVersion || + // column.isCreateDate + ) return; const changeMap = subject.changeMaps.find(changeMap => changeMap.column === column); @@ -62,7 +63,7 @@ export class SubjectChangedColumnsComputer { if (subject.databaseEntity) { // get database value of the column - let databaseValue = column.getEntityValue(subject.databaseEntity); + let databaseValue = column.getEntityValue(subject.databaseEntity, true); // filter out "relational columns" only in the case if there is a relation object in entity if (column.relationMetadata) { @@ -119,6 +120,10 @@ export class SubjectChangedColumnsComputer { databaseValue = DateUtils.simpleJsonToString(databaseValue); break; } + + if (column.transformer) { + normalizedValue = ApplyValueTransformers.transformTo(column.transformer, entityValue); + } } // if value is not changed - then do nothing @@ -168,7 +173,7 @@ export class SubjectChangedColumnsComputer { const databaseRelatedEntityRelationIdMap = relation.getEntityValue(subject.databaseEntity); // if relation ids are equal then we don't need to update anything - const areRelatedIdsEqual = EntityMetadata.compareIds(relatedEntityRelationIdMap, databaseRelatedEntityRelationIdMap); + const areRelatedIdsEqual = OrmUtils.compareIds(relatedEntityRelationIdMap, databaseRelatedEntityRelationIdMap); if (areRelatedIdsEqual) { return; } else { diff --git a/src/persistence/SubjectExecutor.ts b/src/persistence/SubjectExecutor.ts index 1aa64e1d4d..56561e965f 100644 --- a/src/persistence/SubjectExecutor.ts +++ b/src/persistence/SubjectExecutor.ts @@ -1,7 +1,6 @@ import {SapDriver} from "../driver/sap/SapDriver"; import {QueryRunner} from "../query-runner/QueryRunner"; import {Subject} from "./Subject"; -import {PromiseUtils} from "../util/PromiseUtils"; import {SubjectTopoligicalSorter} from "./SubjectTopoligicalSorter"; import {SubjectChangedColumnsComputer} from "./SubjectChangedColumnsComputer"; import {SubjectWithoutIdentifierError} from "../error/SubjectWithoutIdentifierError"; @@ -250,7 +249,7 @@ export class SubjectExecutor { const [groupedInsertSubjects, groupedInsertSubjectKeys] = this.groupBulkSubjects(this.insertSubjects, "insert"); // then we run insertion in the sequential order which is important since we have an ordered subjects - await PromiseUtils.runInSequence(groupedInsertSubjectKeys, async groupName => { + for (const groupName of groupedInsertSubjectKeys) { const subjects = groupedInsertSubjects[groupName]; // we must separately insert entities which does not have any values to insert @@ -334,7 +333,7 @@ export class SubjectExecutor { // insert subjects which must be inserted in separate requests (all default values) if (singleInsertSubjects.length > 0) { - await PromiseUtils.runInSequence(singleInsertSubjects, async subject => { + for (const subject of singleInsertSubjects) { subject.insertedValueSet = subject.createValueSetAndPopChangeMap(); // important to have because query builder sets inserted values into it // for nested set we execute additional queries @@ -363,7 +362,7 @@ export class SubjectExecutor { } else if (subject.metadata.treeType === "materialized-path") { await new MaterializedPathSubjectExecutor(this.queryRunner).insert(subject); } - }); + } } } @@ -378,7 +377,7 @@ export class SubjectExecutor { }); } }); - }); + } } /** @@ -469,7 +468,7 @@ export class SubjectExecutor { // group insertion subjects to make bulk insertions const [groupedRemoveSubjects, groupedRemoveSubjectKeys] = this.groupBulkSubjects(this.removeSubjects, "delete"); - await PromiseUtils.runInSequence(groupedRemoveSubjectKeys, async groupName => { + for (const groupName of groupedRemoveSubjectKeys) { const subjects = groupedRemoveSubjects[groupName]; const deleteMaps = subjects.map(subject => { if (!subject.identifier) @@ -499,7 +498,7 @@ export class SubjectExecutor { .callObservers(false) .execute(); } - }); + } } /** diff --git a/src/persistence/subject-builder/ManyToManySubjectBuilder.ts b/src/persistence/subject-builder/ManyToManySubjectBuilder.ts index 850af6ef39..7d896cdc68 100644 --- a/src/persistence/subject-builder/ManyToManySubjectBuilder.ts +++ b/src/persistence/subject-builder/ManyToManySubjectBuilder.ts @@ -2,7 +2,6 @@ import {Subject} from "../Subject"; import {OrmUtils} from "../../util/OrmUtils"; import {ObjectLiteral} from "../../common/ObjectLiteral"; import {RelationMetadata} from "../../metadata/RelationMetadata"; -import {EntityMetadata} from "../../metadata/EntityMetadata"; /** * Builds operations needs to be executed for many-to-many relations of the given subjects. @@ -150,7 +149,7 @@ export class ManyToManySubjectBuilder { // try to find related entity in the database // by example: find post's category in the database post's categories const relatedEntityExistInDatabase = databaseRelatedEntityIds.find(databaseRelatedEntityRelationId => { - return EntityMetadata.compareIds(databaseRelatedEntityRelationId, relatedEntityRelationIdMap); + return OrmUtils.compareIds(databaseRelatedEntityRelationId, relatedEntityRelationIdMap); }); // if entity is found then don't do anything - it means binding in junction table already exist, we don't need to add anything @@ -207,7 +206,7 @@ export class ManyToManySubjectBuilder { // now from all entities in the persisted entity find only those which aren't found in the db const removedJunctionEntityIds = databaseRelatedEntityIds.filter(existRelationId => { return !changedInverseEntityRelationIds.find(changedRelationId => { - return EntityMetadata.compareIds(changedRelationId, existRelationId); + return OrmUtils.compareIds(changedRelationId, existRelationId); }); }); diff --git a/src/persistence/subject-builder/OneToManySubjectBuilder.ts b/src/persistence/subject-builder/OneToManySubjectBuilder.ts index 25250dfc5a..2578bf1cdb 100644 --- a/src/persistence/subject-builder/OneToManySubjectBuilder.ts +++ b/src/persistence/subject-builder/OneToManySubjectBuilder.ts @@ -117,7 +117,7 @@ export class OneToManySubjectBuilder { // check if this binding really exist in the database // by example: find our category if its already bind in the database const relationIdInDatabaseSubjectRelation = relatedEntityDatabaseRelationIds.find(relatedDatabaseEntityRelationId => { - return OrmUtils.deepCompare(relationIdMap, relatedDatabaseEntityRelationId); + return OrmUtils.compareIds(relationIdMap, relatedDatabaseEntityRelationId); }); // if relationIdMap DOES NOT exist in the subject's relation in the database it means its a new relation and we need to "bind" them diff --git a/src/persistence/subject-builder/OneToOneInverseSideSubjectBuilder.ts b/src/persistence/subject-builder/OneToOneInverseSideSubjectBuilder.ts index f421c5abc7..6912768fdd 100644 --- a/src/persistence/subject-builder/OneToOneInverseSideSubjectBuilder.ts +++ b/src/persistence/subject-builder/OneToOneInverseSideSubjectBuilder.ts @@ -139,7 +139,7 @@ export class OneToOneInverseSideSubjectBuilder { // check if this binding really exist in the database // by example: find our post if its already bind to category in the database and its not equal to what user tries to set - const areRelatedIdEqualWithDatabase = relatedEntityDatabaseRelationId && OrmUtils.deepCompare(relationIdMap, relatedEntityDatabaseRelationId); + const areRelatedIdEqualWithDatabase = relatedEntityDatabaseRelationId && OrmUtils.compareIds(relationIdMap, relatedEntityDatabaseRelationId); // if they aren't equal it means its a new relation and we need to "bind" them // by example: this will tell category to insert into its post relation our post we are working with diff --git a/src/platform/BrowserDirectoryExportedClassesLoader.template b/src/platform/BrowserDirectoryExportedClassesLoader.template new file mode 100644 index 0000000000..39fe932a7b --- /dev/null +++ b/src/platform/BrowserDirectoryExportedClassesLoader.template @@ -0,0 +1,22 @@ +/** + * Dummy functions for replacement via `package.json` in browser builds. + * + * If we don't include these functions typeorm will throw an error on runtime + * as well as during webpack builds. + */ + +import {Logger} from "../logger/Logger"; + +/** + * Loads all exported classes from the given directory. + */ +export function importClassesFromDirectories(logger: Logger, directories: string[], formats = [".js", ".cjs", ".ts"]): Function[] { + return []; +} + +/** + * Loads all json files from the given directory. + */ +export function importJsonsFromDirectories(directories: string[], format = ".json"): any[] { + return []; +} diff --git a/src/platform/BrowserDisabledDriversDummy.template b/src/platform/BrowserDisabledDriversDummy.template index 95cba48bea..9b34705886 100644 --- a/src/platform/BrowserDisabledDriversDummy.template +++ b/src/platform/BrowserDisabledDriversDummy.template @@ -3,8 +3,8 @@ * Using those classes reduces the build size by one third. * * If we don't include those dummy classes (and just disable the driver import - * with `false` in `package.json`) typeorm will throw an error on runtime, - * even if those driver are not used. + * with `false` in `package.json`) typeorm will throw an error on runtime and + * during webpack builds even if those driver are not used. */ /** @@ -37,6 +37,24 @@ export class MongoRepository {} */ export class PostgresDriver {} +/** + * DO NOT IMPORT THIS CLASS - + * This is a dummy class for replacement via `package.json` in browser builds + */ +export class AuroraDataApiDriver {} + +/** + * DO NOT IMPORT THIS CLASS - + * This is a dummy class for replacement via `package.json` in browser builds + */ +export class CockroachDriver {} + +/** + * DO NOT IMPORT THIS CLASS - + * This is a dummy class for replacement via `package.json` in browser builds + */ +export class AuroraDataApiPostgresDriver {} + /** * DO NOT IMPORT THIS CLASS - * This is a dummy class for replacement via `package.json` in browser builds @@ -60,3 +78,15 @@ export class MysqlDriver {} * This is a dummy class for replacement via `package.json` in browser builds */ export class OracleDriver {} + +/** + * DO NOT IMPORT THIS CLASS - + * This is a dummy class for replacement via `package.json` in browser builds + */ +export class SqliteDriver {} + +/** + * DO NOT IMPORT THIS CLASS - + * This is a dummy class for replacement via `package.json` in browser builds + */ +export class BetterSqlite3Driver {} diff --git a/src/platform/BrowserPlatformTools.template b/src/platform/BrowserPlatformTools.template index 216150aaa0..72295f27d3 100644 --- a/src/platform/BrowserPlatformTools.template +++ b/src/platform/BrowserPlatformTools.template @@ -75,6 +75,11 @@ export class PlatformTools { return false; } + static dotenv(pathStr: string): void { + if (this.type === "browser") + throw new Error(`This option/function is not supported in the browser environment. Failed operation: dotenv.config({ path: "${pathStr}" }).`); + } + /** * Gets environment variable. */ @@ -89,7 +94,7 @@ export class PlatformTools { throw new Error(`This option/function is not supported in the browser environment. Failed operation: fs.readFileSync("${filename}").`); return null; } - + static appendFileSync(filename: string, data: any) { if (this.type === "browser") throw new Error(`This option/function is not supported in the browser environment. Failed operation: fs.appendFileSync("${filename}").`); @@ -125,11 +130,11 @@ export class PlatformTools { static logError(prefix: string, error: any) { console.error(prefix + " ", error); } - + static logWarn(prefix: string, warning: any) { console.warn(prefix + " ", warning); } - + static log(message: string) { console.log(message); } @@ -165,4 +170,4 @@ if (typeof window !== "undefined") { // NativeScript uses global, not window if (typeof global !== "undefined") { global.Buffer = require("buffer/").Buffer; -} \ No newline at end of file +} diff --git a/src/platform/PlatformTools.ts b/src/platform/PlatformTools.ts index fffce6cbfd..9d75d8a479 100644 --- a/src/platform/PlatformTools.ts +++ b/src/platform/PlatformTools.ts @@ -1,13 +1,13 @@ import * as path from "path"; import * as fs from "fs"; +import dotenv from "dotenv"; +import chalk from "chalk"; import {highlight, Theme} from "cli-highlight"; export {ReadStream} from "fs"; export {EventEmitter} from "events"; export {Readable, Writable} from "stream"; -const chalk = require("chalk"); - /** * Platform-specific tools. */ @@ -50,8 +50,11 @@ export class PlatformTools { /** * hana */ - case "@sap/hdbext": - return require("@sap/hdbext"); + case "@sap/hana-client": + return require("@sap/hana-client"); + + case "hdb-pool": + return require("hdb-pool"); /** * mysql @@ -80,19 +83,24 @@ export class PlatformTools { case "pg-query-stream": return require("pg-query-stream"); + case "typeorm-aurora-data-api-driver": + return require("typeorm-aurora-data-api-driver"); + /** * redis */ case "redis": return require("redis"); - /** - * ioredis - */ case "ioredis": - case "ioredis/cluster": return require("ioredis"); + /** + * better-sqlite3 + */ + case "better-sqlite3": + return require("better-sqlite3"); + /** * sqlite */ @@ -112,40 +120,21 @@ export class PlatformTools { return require("mssql"); /** - * other modules - */ - case "mkdirp": - return require("mkdirp"); - - case "path": - return require("path"); - - case "debug": - return require("debug"); - - case "app-root-path": - return require("app-root-path"); - - case "glob": - return require("glob"); - - case "typeorm-aurora-data-api-driver": - return require("typeorm-aurora-data-api-driver"); - /** - * default - */ - default: - return require(name); - + * react-native-sqlite + */ + case "react-native-sqlite-storage": + return require("react-native-sqlite-storage"); } } catch (err) { - if (!path.isAbsolute(name) && name.substr(0, 2) !== "./" && name.substr(0, 3) !== "../") { - return require(path.resolve(process.cwd() + "/node_modules/" + name)); - } - - throw err; + return require(path.resolve(process.cwd() + "/node_modules/" + name)); } + + // If nothing above matched and we get here, the package was not listed within PlatformTools + // and is an Invalid Package. To make it explicit that this is NOT the intended use case for + // PlatformTools.load - it's not just a way to replace `require` all willy-nilly - let's throw + // an error. + throw new TypeError(`Invalid Package for PlatformTools.load: ${name}`); } /** @@ -193,6 +182,15 @@ export class PlatformTools { }); } + /** + * Loads a dotenv file into the environment variables. + * + * @param path The file to load as a dotenv configuration + */ + static dotenv(pathStr: string): void { + dotenv.config({ path: pathStr }); + } + /** * Gets environment variable. */ diff --git a/src/query-builder/DeleteQueryBuilder.ts b/src/query-builder/DeleteQueryBuilder.ts index a57afd2d06..05892a7f6f 100644 --- a/src/query-builder/DeleteQueryBuilder.ts +++ b/src/query-builder/DeleteQueryBuilder.ts @@ -2,6 +2,7 @@ import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver"; import {OracleDriver} from "../driver/oracle/OracleDriver"; import {QueryBuilder} from "./QueryBuilder"; import {ObjectLiteral} from "../common/ObjectLiteral"; +import {EntityTarget} from "../common/EntityTarget"; import {Connection} from "../connection/Connection"; import {QueryRunner} from "../query-runner/QueryRunner"; import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver"; @@ -13,8 +14,9 @@ import {ReturningStatementNotSupportedError} from "../error/ReturningStatementNo import {SqljsDriver} from "../driver/sqljs/SqljsDriver"; import {MysqlDriver} from "../driver/mysql/MysqlDriver"; import {BroadcasterResult} from "../subscriber/BroadcasterResult"; -import {EntitySchema, EntityTarget} from "../index"; +import {EntitySchema} from "../index"; import {AuroraDataApiDriver} from "../driver/aurora-data-api/AuroraDataApiDriver"; +import {BetterSqlite3Driver} from "../driver/better-sqlite3/BetterSqlite3Driver"; import {ObserverExecutor} from "../observer/ObserverExecutor"; /** @@ -83,6 +85,10 @@ export class DeleteQueryBuilder extends QueryBuilder implements } else if (driver instanceof OracleDriver) { deleteResult.affected = result; + } else if (driver instanceof BetterSqlite3Driver) { // only works for better-sqlite3 + deleteResult.raw = result; + deleteResult.affected = result.changes; + } else { deleteResult.raw = result; } diff --git a/src/query-builder/InsertQueryBuilder.ts b/src/query-builder/InsertQueryBuilder.ts index 38c67a1d35..8608b5dbe8 100644 --- a/src/query-builder/InsertQueryBuilder.ts +++ b/src/query-builder/InsertQueryBuilder.ts @@ -3,6 +3,7 @@ import {ObserverExecutor} from "../observer/ObserverExecutor"; import {SapDriver} from "../driver/sap/SapDriver"; import {QueryBuilder} from "./QueryBuilder"; import {ObjectLiteral} from "../common/ObjectLiteral"; +import {EntityTarget} from "../common/EntityTarget"; import {QueryDeepPartialEntity} from "./QueryPartialEntity"; import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver"; import {PostgresDriver} from "../driver/postgres/PostgresDriver"; @@ -16,7 +17,7 @@ import {ReturningResultsEntityUpdator} from "./ReturningResultsEntityUpdator"; import {AbstractSqliteDriver} from "../driver/sqlite-abstract/AbstractSqliteDriver"; import {SqljsDriver} from "../driver/sqljs/SqljsDriver"; import {BroadcasterResult} from "../subscriber/BroadcasterResult"; -import {EntitySchema, EntityTarget} from "../"; +import {EntitySchema} from "../entity-schema/EntitySchema"; import {OracleDriver} from "../driver/oracle/OracleDriver"; import {AuroraDataApiDriver} from "../driver/aurora-data-api/AuroraDataApiDriver"; @@ -41,6 +42,20 @@ export class InsertQueryBuilder extends QueryBuilder { * Executes sql generated by query builder and returns raw database results. */ async execute(): Promise { + // console.time(".value sets"); + const valueSets: ObjectLiteral[] = this.getValueSets(); + // console.timeEnd(".value sets"); + + // If user passed empty array of entities then we don't need to do + // anything. + // + // Fixes GitHub issues #3111 and #5734. If we were to let this through + // we would run into problems downstream, like subscribers getting + // invoked with the empty array where they expect an entity, and SQL + // queries with an empty VALUES clause. + if (valueSets.length === 0) + return new InsertResult(); + // console.time("QueryBuilder.execute"); // console.time(".database stuff"); const queryRunner = this.obtainQueryRunner(); @@ -55,9 +70,6 @@ export class InsertQueryBuilder extends QueryBuilder { } // console.timeEnd(".database stuff"); - // console.time(".value sets"); - const valueSets: ObjectLiteral[] = this.getValueSets(); - // console.timeEnd(".value sets"); // call before insertion methods in listeners and subscribers if (this.expressionMap.callListeners === true && this.expressionMap.mainAlias!.hasMetadata) { @@ -115,8 +127,9 @@ export class InsertQueryBuilder extends QueryBuilder { // close transaction if we started it // console.time(".commit"); - if (transactionStartedByUs) + if (transactionStartedByUs) { await queryRunner.commitTransaction(); + } // second case is when operation is executed without transaction and at the same time // nobody started transaction from the above @@ -160,7 +173,7 @@ export class InsertQueryBuilder extends QueryBuilder { /** * Specifies INTO which entity's table insertion will be executed. */ - into(entityTarget: EntityTarget, columns?: string[]): InsertQueryBuilder { + into(entityTarget: EntityTarget, columns?: string[]): InsertQueryBuilder { entityTarget = entityTarget instanceof EntitySchema ? entityTarget.options.name!! : entityTarget; const mainAlias = this.createFromAlias(entityTarget); this.expressionMap.setMainAlias(mainAlias); @@ -429,7 +442,8 @@ export class InsertQueryBuilder extends QueryBuilder { } // newly inserted entities always have a version equal to 1 (first version) - if (column.isVersion) { + // also, user-specified version must be empty + if (column.isVersion && value === undefined) { expression += "1"; // } else if (column.isNestedSetLeft) { @@ -506,6 +520,8 @@ export class InsertQueryBuilder extends QueryBuilder { } else { expression += `ST_GeomFromGeoJSON(${this.connection.driver.createParameter(paramName, parametersCount)})::${column.type}`; } + } else if (this.connection.driver instanceof SqlServerDriver && this.connection.driver.spatialTypes.indexOf(column.type) !== -1) { + expression += column.type + "::STGeomFromText(" + this.connection.driver.createParameter(paramName, parametersCount) + ", " + (column.srid || "0") + ")"; } else { expression += this.connection.driver.createParameter(paramName, parametersCount); } @@ -583,7 +599,7 @@ export class InsertQueryBuilder extends QueryBuilder { * Gets array of values need to be inserted into the target table. */ protected getValueSets(): ObjectLiteral[] { - if (Array.isArray(this.expressionMap.valuesSet) && this.expressionMap.valuesSet.length > 0) + if (Array.isArray(this.expressionMap.valuesSet)) return this.expressionMap.valuesSet; if (this.expressionMap.valuesSet instanceof Object) diff --git a/src/query-builder/QueryBuilder.ts b/src/query-builder/QueryBuilder.ts index ea78df9e9b..5dd5503d12 100644 --- a/src/query-builder/QueryBuilder.ts +++ b/src/query-builder/QueryBuilder.ts @@ -8,7 +8,7 @@ import {DeleteQueryBuilder} from "./DeleteQueryBuilder"; import {SoftDeleteQueryBuilder} from "./SoftDeleteQueryBuilder"; import {InsertQueryBuilder} from "./InsertQueryBuilder"; import {RelationQueryBuilder} from "./RelationQueryBuilder"; -import {ObjectType} from "../common/ObjectType"; +import {EntityTarget} from "../common/EntityTarget"; import {Alias} from "./Alias"; import {Brackets} from "./Brackets"; import {QueryDeepPartialEntity} from "./QueryPartialEntity"; @@ -17,9 +17,10 @@ import {ColumnMetadata} from "../metadata/ColumnMetadata"; import {SqljsDriver} from "../driver/sqljs/SqljsDriver"; import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver"; import {OracleDriver} from "../driver/oracle/OracleDriver"; -import {EntitySchema, EntityTarget} from "../"; +import {EntitySchema} from "../"; import {FindOperator} from "../find-options/FindOperator"; import {In} from "../find-options/operator/In"; +import {EntityColumnNotFound} from "../error/EntityColumnNotFound"; // todo: completely cover query builder with tests // todo: entityOrProperty can be target name. implement proper behaviour if it is. @@ -186,17 +187,7 @@ export abstract class QueryBuilder { /** * Creates UPDATE query for the given entity and applies given update values. */ - update(entity: ObjectType, updateSet?: QueryDeepPartialEntity): UpdateQueryBuilder; - - /** - * Creates UPDATE query for the given entity and applies given update values. - */ - update(entity: EntitySchema, updateSet?: QueryDeepPartialEntity): UpdateQueryBuilder; - - /** - * Creates UPDATE query for the given entity and applies given update values. - */ - update(entity: EntityTarget, updateSet?: QueryDeepPartialEntity): UpdateQueryBuilder; + update(entity: EntityTarget, updateSet?: QueryDeepPartialEntity): UpdateQueryBuilder; /** * Creates UPDATE query for the given table name and applies given update values. @@ -206,7 +197,7 @@ export abstract class QueryBuilder { /** * Creates UPDATE query and applies given update values. */ - update(entityOrTableNameUpdateSet?: string|Function|EntitySchema|ObjectLiteral, maybeUpdateSet?: ObjectLiteral): UpdateQueryBuilder { + update(entityOrTableNameUpdateSet?: EntityTarget|ObjectLiteral, maybeUpdateSet?: ObjectLiteral): UpdateQueryBuilder { const updateSet = maybeUpdateSet ? maybeUpdateSet : entityOrTableNameUpdateSet as ObjectLiteral|undefined; entityOrTableNameUpdateSet = entityOrTableNameUpdateSet instanceof EntitySchema ? entityOrTableNameUpdateSet.options.name : entityOrTableNameUpdateSet; @@ -270,7 +261,7 @@ export abstract class QueryBuilder { /** * Sets entity's relation with which this query builder gonna work. */ - relation(entityTarget: ObjectType|string, propertyPath: string): RelationQueryBuilder; + relation(entityTarget: EntityTarget, propertyPath: string): RelationQueryBuilder; /** * Sets entity's relation with which this query builder gonna work. @@ -302,7 +293,7 @@ export abstract class QueryBuilder { * * todo: move this method to manager? or create a shortcut? */ - hasRelation(target: ObjectType|string, relation: string): boolean; + hasRelation(target: EntityTarget, relation: string): boolean; /** * Checks if given relations exist in the entity. @@ -310,7 +301,7 @@ export abstract class QueryBuilder { * * todo: move this method to manager? or create a shortcut? */ - hasRelation(target: ObjectType|string, relation: string[]): boolean; + hasRelation(target: EntityTarget, relation: string[]): boolean; /** * Checks if given relation or relations exist in the entity. @@ -318,7 +309,7 @@ export abstract class QueryBuilder { * * todo: move this method to manager? or create a shortcut? */ - hasRelation(target: ObjectType|string, relation: string|string[]): boolean { + hasRelation(target: EntityTarget, relation: string|string[]): boolean { const entityMetadata = this.connection.getMetadata(target); const relations = Array.isArray(relation) ? relation : [relation]; return relations.every(relation => { @@ -555,21 +546,25 @@ export abstract class QueryBuilder { }); } else { - let subQuery: string = ""; - if (entityTarget instanceof Function) { - const subQueryBuilder: SelectQueryBuilder = (entityTarget as any)(((this as any) as SelectQueryBuilder).subQuery()); - this.setParameters(subQueryBuilder.getParameters()); - subQuery = subQueryBuilder.getQuery(); - - } else if (typeof entityTarget === "string") { - subQuery = entityTarget; + if (typeof entityTarget === "string") { + const isSubquery = entityTarget.substr(0, 1) === "(" && entityTarget.substr(-1) === ")"; + + return this.expressionMap.createAlias({ + type: "from", + name: aliasName, + tablePath: !isSubquery ? entityTarget as string : undefined, + subQuery: isSubquery ? entityTarget : undefined, + }); } - const isSubQuery = entityTarget instanceof Function || (typeof entityTarget === "string" && entityTarget.substr(0, 1) === "(" && entityTarget.substr(-1) === ")"); + + const subQueryBuilder: SelectQueryBuilder = (entityTarget as any)(((this as any) as SelectQueryBuilder).subQuery()); + this.setParameters(subQueryBuilder.getParameters()); + const subquery = subQueryBuilder.getQuery(); + return this.expressionMap.createAlias({ type: "from", name: aliasName, - tablePath: isSubQuery === false ? entityTarget as string : undefined, - subQuery: isSubQuery === true ? subQuery : undefined, + subQuery: subquery }); } } @@ -606,7 +601,10 @@ export abstract class QueryBuilder { * Creates "WHERE" expression. */ protected createWhereExpression() { - let conditions = this.createWhereExpressionString(); + const conditionsArray = []; + + const whereExpression = this.createWhereExpressionString(); + whereExpression.trim() && conditionsArray.push(this.createWhereExpressionString()); if (this.expressionMap.mainAlias!.hasMetadata) { const metadata = this.expressionMap.mainAlias!.metadata; @@ -617,7 +615,7 @@ export abstract class QueryBuilder { : metadata.deleteDateColumn.propertyName; const condition = `${this.replacePropertyNames(column)} IS NULL`; - conditions = `${ conditions.length ? "(" + conditions + ") AND" : "" } ${condition}`; + conditionsArray.push(condition); } if (metadata.discriminatorColumn && metadata.parentEntityMetadata) { @@ -626,17 +624,22 @@ export abstract class QueryBuilder { : metadata.discriminatorColumn.databaseName; const condition = `${this.replacePropertyNames(column)} IN (:...discriminatorColumnValues)`; - return ` WHERE ${ conditions.length ? "(" + conditions + ") AND" : "" } ${condition}`; + conditionsArray.push(condition); } } - if (!conditions.length) // TODO copy in to discriminator condition - return this.expressionMap.extraAppendedAndWhereCondition ? " WHERE " + this.replacePropertyNames(this.expressionMap.extraAppendedAndWhereCondition) : ""; - - if (this.expressionMap.extraAppendedAndWhereCondition) - return " WHERE (" + conditions + ") AND " + this.replacePropertyNames(this.expressionMap.extraAppendedAndWhereCondition); + if (this.expressionMap.extraAppendedAndWhereCondition) { + const condition = this.replacePropertyNames(this.expressionMap.extraAppendedAndWhereCondition); + conditionsArray.push(condition); + } - return " WHERE " + conditions; + if (!conditionsArray.length) { + return " "; + } else if (conditionsArray.length === 1) { + return ` WHERE ${conditionsArray[0]}`; + } else { + return ` WHERE ( ${conditionsArray.join(" ) AND ( ")} )`; + } } /** @@ -809,6 +812,11 @@ export abstract class QueryBuilder { return propertyPaths.map((propertyPath, propertyIndex) => { const columns = this.expressionMap.mainAlias!.metadata.findColumnsWithPropertyPath(propertyPath); + + if (!columns.length) { + throw new EntityColumnNotFound(propertyPath); + } + return columns.map((column, columnIndex) => { const aliasPath = this.expressionMap.aliasNamePrefixingEnabled ? `${this.alias}.${propertyPath}` : column.propertyPath; @@ -882,7 +890,7 @@ export abstract class QueryBuilder { * Creates a query builder used to execute sql queries inside this query builder. */ protected obtainQueryRunner() { - return this.queryRunner || this.connection.createQueryRunner("master"); + return this.queryRunner || this.connection.createQueryRunner(); } } diff --git a/src/query-builder/QueryExpressionMap.ts b/src/query-builder/QueryExpressionMap.ts index fa31f0cf02..00675e4e2d 100644 --- a/src/query-builder/QueryExpressionMap.ts +++ b/src/query-builder/QueryExpressionMap.ts @@ -151,7 +151,7 @@ export class QueryExpressionMap { /** * Locking mode. */ - lockMode?: "optimistic"|"pessimistic_read"|"pessimistic_write"|"dirty_read"; + lockMode?: "optimistic"|"pessimistic_read"|"pessimistic_write"|"dirty_read"|"pessimistic_partial_write"|"pessimistic_write_or_fail"|"for_no_key_update"; /** * Current version of the entity, used for locking. diff --git a/src/query-builder/QueryPartialEntity.ts b/src/query-builder/QueryPartialEntity.ts index 1e6ccfa301..6889c547e0 100644 --- a/src/query-builder/QueryPartialEntity.ts +++ b/src/query-builder/QueryPartialEntity.ts @@ -11,7 +11,9 @@ export type QueryPartialEntity = { */ export type QueryDeepPartialEntity = { [P in keyof T]?: - T[P] extends Array ? Array> : - T[P] extends ReadonlyArray ? ReadonlyArray> : - QueryDeepPartialEntity | (() => string); + ( + T[P] extends Array ? Array> : + T[P] extends ReadonlyArray ? ReadonlyArray> : + QueryDeepPartialEntity + ) | (() => string); }; diff --git a/src/query-builder/RelationIdLoader.ts b/src/query-builder/RelationIdLoader.ts index c763a2d220..7c2a8b57ea 100644 --- a/src/query-builder/RelationIdLoader.ts +++ b/src/query-builder/RelationIdLoader.ts @@ -1,6 +1,6 @@ import {Connection, ObjectLiteral, SelectQueryBuilder} from "../"; -import {ColumnMetadata} from "../metadata/ColumnMetadata"; import {RelationMetadata} from "../metadata/RelationMetadata"; +import {ColumnMetadata} from "../metadata/ColumnMetadata"; /** * Loads relation ids for the given entities. diff --git a/src/query-builder/ReturningResultsEntityUpdator.ts b/src/query-builder/ReturningResultsEntityUpdator.ts index 2db45f882b..9f308e3d4e 100644 --- a/src/query-builder/ReturningResultsEntityUpdator.ts +++ b/src/query-builder/ReturningResultsEntityUpdator.ts @@ -93,7 +93,7 @@ export class ReturningResultsEntityUpdator { } // get all values generated by a database for us const result = Array.isArray(insertResult.raw) ? insertResult.raw[entityIndex] : insertResult.raw; - const generatedMap = this.queryRunner.connection.driver.createGeneratedMap(metadata, result) || {}; + const generatedMap = this.queryRunner.connection.driver.createGeneratedMap(metadata, result, entityIndex, entities.length) || {}; // if database does not support uuid generation we need to get uuid values // generated by orm and set them to the generatedMap @@ -117,26 +117,33 @@ export class ReturningResultsEntityUpdator { // for postgres and mssql we use returning/output statement to get values of inserted default and generated values // for other drivers we have to re-select this data from the database if (this.queryRunner.connection.driver.isReturningSqlSupported() === false && insertionColumns.length > 0) { - await Promise.all(entities.map(async (entity, entityIndex) => { + let entityIds: any[] = entities.map((entity) => { const entityId = metadata.getEntityIdMap(entity)!; - - // to select just inserted entity we need a criteria to select by. - // for newly inserted entities in drivers which do not support returning statement - // row identifier can only be an increment column - // (since its the only thing that can be generated by those databases) - // or (and) other primary key which is defined by a user and inserted value has it - - const returningResult: any = await this.queryRunner.manager - .createQueryBuilder() - .select(metadata.primaryColumns.map(column => metadata.targetName + "." + column.propertyPath)) - .addSelect(insertionColumns.map(column => metadata.targetName + "." + column.propertyPath)) - .from(metadata.target, metadata.targetName) - .where(entityId) - .setOption("create-pojo") // use POJO because created object can contain default values, e.g. property = null and those properties maight be overridden by merge process - .getOne(); - - this.queryRunner.manager.merge(metadata.target as any, generatedMaps[entityIndex], returningResult); - })); + return entityId; + }); + + // TODO: This is to make the behavior match current behavior of the `next` branch + // TODO: It's technically not correct but is put in place during the merge to keep behavior the same + entityIds = entityIds.filter(e => typeof e !== "undefined"); + + // to select just inserted entities we need a criteria to select by. + // for newly inserted entities in drivers which do not support returning statement + // row identifier can only be an increment column + // (since its the only thing that can be generated by those databases) + // or (and) other primary key which is defined by a user and inserted value has it + + const returningResult: any = await this.queryRunner.manager + .createQueryBuilder() + .select(metadata.primaryColumns.map(column => metadata.targetName + "." + column.propertyPath)) + .addSelect(insertionColumns.map(column => metadata.targetName + "." + column.propertyPath)) + .from(metadata.target, metadata.targetName) + .where(entityIds) + .setOption("create-pojo") // use POJO because created object can contain default values, e.g. property = null and those properties maight be overridden by merge process + .getMany(); + + entities.forEach((entity, entityIndex) => { + this.queryRunner.manager.merge(metadata.target as any, generatedMaps[entityIndex], returningResult[entityIndex]); + }); } entities.forEach((entity, entityIndex) => { diff --git a/src/query-builder/SelectQueryBuilder.ts b/src/query-builder/SelectQueryBuilder.ts index ea65bce520..7a94e282bc 100644 --- a/src/query-builder/SelectQueryBuilder.ts +++ b/src/query-builder/SelectQueryBuilder.ts @@ -27,6 +27,7 @@ import {EntityMetadata} from "../metadata/EntityMetadata"; import {ColumnMetadata} from "../metadata/ColumnMetadata"; import {OrderByCondition} from "../find-options/OrderByCondition"; import {QueryExpressionMap} from "./QueryExpressionMap"; +import {EntityTarget} from "../common/EntityTarget"; import {QueryRunner} from "../query-runner/QueryRunner"; import {WhereExpression} from "./WhereExpression"; import {Brackets} from "./Brackets"; @@ -51,7 +52,8 @@ import {ObjectUtils} from "../util/ObjectUtils"; import {DriverUtils} from "../driver/DriverUtils"; import {AuroraDataApiDriver} from "../driver/aurora-data-api/AuroraDataApiDriver"; import {ApplyValueTransformers} from "../util/ApplyValueTransformers"; -import {Connection, EntityTarget} from ".."; +import {Connection} from ".."; +import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver"; /** * Allows to build complex sql queries in a fashion way and execute those queries. @@ -779,7 +781,7 @@ export class SelectQueryBuilder extends QueryBuilder implements where(where: Brackets|string|((qb: this) => string)|FindOptionsWhere, parameters?: ObjectLiteral): this { this.expressionMap.wheres = []; // don't move this block below since computeWhereParameter can add where expressions - if (where && typeof where === "object" && !(where instanceof Brackets)) { + if (where && typeof where === "object" && !(where instanceof Brackets) && !Array.isArray(where)) { this.findOptions.where = where; } else { @@ -1049,12 +1051,12 @@ export class SelectQueryBuilder extends QueryBuilder implements /** * Sets locking mode. */ - setLock(lockMode: "pessimistic_read"|"pessimistic_write"|"dirty_read"): this; + setLock(lockMode: "pessimistic_read"|"pessimistic_write"|"dirty_read"|"pessimistic_partial_write"|"pessimistic_write_or_fail"|"for_no_key_update"): this; /** * Sets locking mode. */ - setLock(lockMode: "optimistic"|"pessimistic_read"|"pessimistic_write"|"dirty_read", lockVersion?: number|Date): this { + setLock(lockMode: "optimistic"|"pessimistic_read"|"pessimistic_write"|"dirty_read"|"pessimistic_partial_write"|"pessimistic_write_or_fail"|"for_no_key_update", lockVersion?: number|Date): this { this.expressionMap.lockMode = lockMode; this.expressionMap.lockVersion = lockVersion; return this; @@ -1776,6 +1778,26 @@ export class SelectQueryBuilder extends QueryBuilder implements } else { throw new LockNotSupportedOnGivenDriverError(); } + case "pessimistic_partial_write": + if (driver instanceof PostgresDriver) { + return " FOR UPDATE SKIP LOCKED"; + + } else { + throw new LockNotSupportedOnGivenDriverError(); + } + case "pessimistic_write_or_fail": + if (driver instanceof PostgresDriver) { + return " FOR UPDATE NOWAIT"; + } else { + throw new LockNotSupportedOnGivenDriverError(); + } + + case "for_no_key_update": + if (driver instanceof PostgresDriver) { + return " FOR NO KEY UPDATE"; + } else { + throw new LockNotSupportedOnGivenDriverError(); + } default: return ""; } @@ -2006,6 +2028,16 @@ export class SelectQueryBuilder extends QueryBuilder implements return `${distinctAlias}.${propertyName}`; }).join(" || ") + ")) as \"cnt\""; + } else if (this.connection.driver instanceof CockroachDriver) { + countSql = `COUNT(DISTINCT(CONCAT(` + metadata.primaryColumns.map((primaryColumn, index) => { + const propertyName = this.escape(primaryColumn.databaseName); + return `${distinctAlias}.${propertyName}::text`; + }).join(", ") + "))) as \"cnt\""; + } else if (this.connection.driver instanceof OracleDriver) { + countSql = `COUNT(DISTINCT(` + metadata.primaryColumns.map((primaryColumn, index) => { + const propertyName = this.escape(primaryColumn.databaseName); + return `${distinctAlias}.${propertyName}`; + }).join(" || ") + ")) as \"cnt\""; } else { countSql = `COUNT(DISTINCT(CONCAT(` + metadata.primaryColumns.map((primaryColumn, index) => { const propertyName = this.escape(primaryColumn.databaseName); @@ -2029,7 +2061,6 @@ export class SelectQueryBuilder extends QueryBuilder implements .take(undefined) .select(countSql) .setOption("disable-global-order") - // .setFindOptions({ where: this.findOptions.where }) .loadRawResults(queryRunner); if (!results || !results[0] || !results[0]["cnt"]) @@ -2046,10 +2077,7 @@ export class SelectQueryBuilder extends QueryBuilder implements if (!this.expressionMap.mainAlias) throw new Error(`Alias is not set. Use "from" method to set an alias.`); - const cloneQb1 = this.clone(); - const cloneQb2 = this.clone(); - - if ((this.expressionMap.lockMode === "pessimistic_read" || this.expressionMap.lockMode === "pessimistic_write") && !queryRunner.isTransactionActive) + if ((this.expressionMap.lockMode === "pessimistic_read" || this.expressionMap.lockMode === "pessimistic_write" || this.expressionMap.lockMode === "pessimistic_partial_write" || this.expressionMap.lockMode === "pessimistic_write_or_fail" || this.expressionMap.lockMode === "for_no_key_update") && !queryRunner.isTransactionActive) throw new PessimisticLockTransactionRequiredError(); if (this.expressionMap.lockMode === "optimistic") { @@ -2084,22 +2112,20 @@ export class SelectQueryBuilder extends QueryBuilder implements const columnAlias = this.escape(DriverUtils.buildColumnAlias(this.connection.driver, mainAliasName, primaryColumn.databaseName)); if (!orderBys[columnAlias]) // make sure we aren't overriding user-defined order in inverse direction orderBys[columnAlias] = "ASC"; - return `${distinctAlias}.${columnAlias} as "ids_${DriverUtils.buildColumnAlias(this.connection.driver, mainAliasName, primaryColumn.databaseName)}"`; - }); - const clonnedQb = cloneQb1 - // .setFindOptions({ - // select: this.findOptions.select, - // relations: this.findOptions.relations, - // options: this.findOptions.options, - // where: this.findOptions.where - // }) - .orderBy(); + const alias = DriverUtils.buildColumnAlias( + this.connection.driver, + "ids_" + mainAliasName, + primaryColumn.databaseName + ); + + return `${distinctAlias}.${columnAlias} as "${alias}"`; + }); rawResults = await new SelectQueryBuilder(this.connection, queryRunner) .select(`DISTINCT ${querySelects.join(", ")}`) .addSelect(selects) - .from(`(${clonnedQb.getQuery()})`, "distinctAlias") + .from(`(${this.clone().orderBy().getQuery()})`, "distinctAlias") .offset(this.expressionMap.skip) .limit(this.expressionMap.take) .orderBy(orderBys) @@ -2120,7 +2146,13 @@ export class SelectQueryBuilder extends QueryBuilder implements }).join(" AND "); }).join(" OR "); } else { - const ids = rawResults.map(result => result["ids_" + DriverUtils.buildColumnAlias(this.connection.driver, mainAliasName, metadata.primaryColumns[0].databaseName)]); + const alias = DriverUtils.buildColumnAlias( + this.connection.driver, + "ids_" + mainAliasName, + metadata.primaryColumns[0].databaseName + ); + + const ids = rawResults.map(result => result[alias]); const areAllNumbers = ids.every((id: any) => typeof id === "number"); if (areAllNumbers) { // fixes #190. if all numbers then its safe to perform query without parameter @@ -2130,8 +2162,7 @@ export class SelectQueryBuilder extends QueryBuilder implements condition = mainAliasName + "." + metadata.primaryColumns[0].propertyPath + " IN (:...orm_distinct_ids)"; } } - rawResults = await cloneQb2 - // .setFindOptions(this.findOptions) + rawResults = await this.clone() .mergeExpressionMap({ extraAppendedAndWhereCondition: condition }) .setParameters(parameters) .loadRawResults(queryRunner); diff --git a/src/query-builder/SoftDeleteQueryBuilder.ts b/src/query-builder/SoftDeleteQueryBuilder.ts index 2126f74cc5..5b52c5c08f 100644 --- a/src/query-builder/SoftDeleteQueryBuilder.ts +++ b/src/query-builder/SoftDeleteQueryBuilder.ts @@ -1,7 +1,7 @@ import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver"; import {QueryBuilder} from "./QueryBuilder"; import {ObjectLiteral} from "../common/ObjectLiteral"; -import {ObjectType} from "../common/ObjectType"; +import {EntityTarget} from "../common/EntityTarget"; import {Connection} from "../connection/Connection"; import {QueryRunner} from "../query-runner/QueryRunner"; import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver"; @@ -142,7 +142,7 @@ export class SoftDeleteQueryBuilder extends QueryBuilder impleme * Specifies FROM which entity's table select/update/delete/soft-delete will be executed. * Also sets a main string alias of the selection data. */ - from(entityTarget: ObjectType|EntitySchema|string, aliasName?: string): SoftDeleteQueryBuilder { + from(entityTarget: EntityTarget, aliasName?: string): SoftDeleteQueryBuilder { entityTarget = entityTarget instanceof EntitySchema ? entityTarget.options.name! : entityTarget; const mainAlias = this.createFromAlias(entityTarget, aliasName); this.expressionMap.setMainAlias(mainAlias); diff --git a/src/query-builder/UpdateQueryBuilder.ts b/src/query-builder/UpdateQueryBuilder.ts index 6602d4ff91..bb502d9dcd 100644 --- a/src/query-builder/UpdateQueryBuilder.ts +++ b/src/query-builder/UpdateQueryBuilder.ts @@ -25,6 +25,7 @@ import {UpdateValuesMissingError} from "../error/UpdateValuesMissingError"; import {EntityColumnNotFound} from "../error/EntityColumnNotFound"; import {QueryDeepPartialEntity} from "./QueryPartialEntity"; import {AuroraDataApiDriver} from "../driver/aurora-data-api/AuroraDataApiDriver"; +import {BetterSqlite3Driver} from "../driver/better-sqlite3/BetterSqlite3Driver"; /** * Allows to build complex sql queries in a fashion way and execute those queries. @@ -109,6 +110,10 @@ export class UpdateQueryBuilder extends QueryBuilder implements updateResult.raw = result; updateResult.affected = result.affectedRows; } + else if (this.connection.driver instanceof BetterSqlite3Driver) { // only works for better-sqlite3 + updateResult.raw = result; + updateResult.affected = result.changes; + } else { updateResult.raw = result; } @@ -473,6 +478,8 @@ export class UpdateQueryBuilder extends QueryBuilder implements } else { expression = `ST_GeomFromGeoJSON(${this.connection.driver.createParameter(paramName, parametersCount)})::${column.type}`; } + } else if (this.connection.driver instanceof SqlServerDriver && this.connection.driver.spatialTypes.indexOf(column.type) !== -1) { + expression = column.type + "::STGeomFromText(" + this.connection.driver.createParameter(paramName, parametersCount) + ", " + (column.srid || "0") + ")"; } else { expression = this.connection.driver.createParameter(paramName, parametersCount); } diff --git a/src/query-builder/transformer/RawSqlResultsToEntityTransformer.ts b/src/query-builder/transformer/RawSqlResultsToEntityTransformer.ts index 15bae0535e..397b37a1c7 100644 --- a/src/query-builder/transformer/RawSqlResultsToEntityTransformer.ts +++ b/src/query-builder/transformer/RawSqlResultsToEntityTransformer.ts @@ -74,7 +74,6 @@ export class RawSqlResultsToEntityTransformer { return keyValue; }).join("_"); // todo: check partial - if (!id) return; const items = map.get(id); if (!items) { @@ -217,7 +216,7 @@ export class RawSqlResultsToEntityTransformer { const idMaps = rawRelationIdResult.results.map(result => { const entityPrimaryIds = this.extractEntityPrimaryIds(relation, result); - if (EntityMetadata.compareIds(entityPrimaryIds, valueMap) === false) + if (OrmUtils.compareIds(entityPrimaryIds, valueMap) === false) return; let columns: ColumnMetadata[]; diff --git a/src/query-runner/BaseQueryRunner.ts b/src/query-runner/BaseQueryRunner.ts index 72616c1f5f..6e73f226e5 100644 --- a/src/query-runner/BaseQueryRunner.ts +++ b/src/query-runner/BaseQueryRunner.ts @@ -3,12 +3,12 @@ import {Query} from "../driver/Query"; import {SqlInMemory} from "../driver/SqlInMemory"; import {SqlServerConnectionOptions} from "../driver/sqlserver/SqlServerConnectionOptions"; import {View} from "../schema-builder/view/View"; -import {PromiseUtils} from "../util/PromiseUtils"; import {Connection} from "../connection/Connection"; import {Table} from "../schema-builder/table/Table"; import {EntityManager} from "../entity-manager/EntityManager"; import {TableColumn} from "../schema-builder/table/TableColumn"; import {Broadcaster} from "../subscriber/Broadcaster"; +import {ReplicationMode} from "../driver/types/ReplicationMode"; export abstract class BaseQueryRunner { @@ -82,7 +82,7 @@ export abstract class BaseQueryRunner { * Used for replication. * If replication is not setup its value is ignored. */ - protected mode: "master"|"slave"; + protected mode: ReplicationMode; // ------------------------------------------------------------------------- // Public Abstract Methods @@ -176,14 +176,18 @@ export abstract class BaseQueryRunner { * Executes up sql queries. */ async executeMemoryUpSql(): Promise { - await PromiseUtils.runInSequence(this.sqlInMemory.upQueries, upQuery => this.query(upQuery.query, upQuery.parameters)); + for (const {query, parameters} of this.sqlInMemory.upQueries) { + await this.query(query, parameters); + } } /** * Executes down sql queries. */ async executeMemoryDownSql(): Promise { - await PromiseUtils.runInSequence(this.sqlInMemory.downQueries.reverse(), downQuery => this.query(downQuery.query, downQuery.parameters)); + for (const {query, parameters} of this.sqlInMemory.downQueries.reverse()) { + await this.query(query, parameters); + } } // ------------------------------------------------------------------------- @@ -312,30 +316,6 @@ export abstract class BaseQueryRunner { return false; } - /** - * Checks if column display width is by default. Used only for MySQL. - */ - protected isDefaultColumnWidth(table: Table, column: TableColumn, width: number): boolean { - // if table have metadata, we check if length is specified in column metadata - if (this.connection.hasMetadata(table.name)) { - const metadata = this.connection.getMetadata(table.name); - const columnMetadata = metadata.findColumnWithDatabaseName(column.name); - if (columnMetadata && columnMetadata.width) - return false; - } - - if (this.connection.driver.dataTypeDefaults - && this.connection.driver.dataTypeDefaults[column.type] - && this.connection.driver.dataTypeDefaults[column.type].width) { - if (column.unsigned && column.type !== "bigint") { - return this.connection.driver.dataTypeDefaults[column.type].width === width + 1; - } - return this.connection.driver.dataTypeDefaults[column.type].width === width; - } - - return false; - } - /** * Checks if column precision is by default. */ @@ -394,7 +374,9 @@ export abstract class BaseQueryRunner { if (this.sqlMemoryMode === true) return Promise.resolve() as Promise; - await PromiseUtils.runInSequence(upQueries, upQuery => this.query(upQuery.query, upQuery.parameters)); + for (const {query, parameters} of upQueries) { + await this.query(query, parameters); + } } } diff --git a/src/repository/AbstractRepository.ts b/src/repository/AbstractRepository.ts index ec16794128..7a856ca501 100644 --- a/src/repository/AbstractRepository.ts +++ b/src/repository/AbstractRepository.ts @@ -2,12 +2,12 @@ import {ObjectLiteral} from "../common/ObjectLiteral"; import {EntityManager} from "../entity-manager/EntityManager"; import {Repository} from "./Repository"; import {TreeRepository} from "./TreeRepository"; +import {EntityTarget} from "../common/EntityTarget"; import {ObjectType} from "../common/ObjectType"; import {CustomRepositoryDoesNotHaveEntityError} from "../error/CustomRepositoryDoesNotHaveEntityError"; import {getMetadataArgsStorage} from "../index"; import {CustomRepositoryNotFoundError} from "../error/CustomRepositoryNotFoundError"; import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder"; -import {EntitySchema} from "../entity-schema/EntitySchema"; /** * Provides abstract class for custom repositories that do not inherit from original orm Repository. @@ -100,7 +100,7 @@ export class AbstractRepository { * Gets custom repository's managed entity. * If given custom repository does not manage any entity then undefined will be returned. */ - private getCustomRepositoryTarget(customRepository: any): Function|string|EntitySchema|undefined { + private getCustomRepositoryTarget(customRepository: any): EntityTarget|undefined { const entityRepositoryMetadataArgs = getMetadataArgsStorage().entityRepositories.find(repository => { return repository.target === (customRepository instanceof Function ? customRepository : (customRepository as any).constructor); }); diff --git a/src/repository/BaseEntity.ts b/src/repository/BaseEntity.ts index 38ab40ff1e..2c9f13d78a 100644 --- a/src/repository/BaseEntity.ts +++ b/src/repository/BaseEntity.ts @@ -1,15 +1,15 @@ import {Repository} from "./Repository"; import {FindOptions, FindOptionsWhere, getConnection} from "../index"; import {DeepPartial} from "../common/DeepPartial"; -import {ObjectType} from "../common/ObjectType"; +import {SaveOptions} from "./SaveOptions"; +import {RemoveOptions} from "./RemoveOptions"; import {Connection} from "../connection/Connection"; -import {ObjectID} from "../driver/mongodb/typings"; -import {DeleteResult} from "../query-builder/result/DeleteResult"; +import {ObjectType} from "../common/ObjectType"; +import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder"; import {InsertResult} from "../query-builder/result/InsertResult"; import {UpdateResult} from "../query-builder/result/UpdateResult"; -import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder"; -import {RemoveOptions} from "./RemoveOptions"; -import {SaveOptions} from "./SaveOptions"; +import {DeleteResult} from "../query-builder/result/DeleteResult"; +import {ObjectID} from "../driver/mongodb/typings"; import {ObjectUtils} from "../util/ObjectUtils"; import {QueryDeepPartialEntity} from "../query-builder/QueryPartialEntity"; import * as Observable from "zen-observable"; @@ -56,6 +56,20 @@ export class BaseEntity { return (this.constructor as any).getRepository().remove(this, options); } + /** + * Records the delete date of current entity. + */ + softRemove(options?: SaveOptions): Promise { + return (this.constructor as any).getRepository().softRemove(this, options); + } + + /** + * Recovers a given entity in the database. + */ + recover(options?: SaveOptions): Promise { + return (this.constructor as any).getRepository().recover(this, options); + } + /** * Reloads entity data from the database. */ @@ -148,7 +162,7 @@ export class BaseEntity { } /** - * Creates a new entity from the given plan javascript object. If entity already exist in the database, then + * Creates a new entity from the given plain javascript object. If entity already exist in the database, then * it loads it (and everything related to it), replaces all values with the new ones from the given object * and returns this new entity. This new entity is actually a loaded from the db entity with all properties * replaced from the new object. @@ -196,6 +210,23 @@ export class BaseEntity { return (this as any).getRepository().remove(entityOrEntities as any, options); } + /** + * Records the delete date of all given entities. + */ + static softRemove(this: ObjectType, entities: T[], options?: SaveOptions): Promise; + + /** + * Records the delete date of a given entity. + */ + static softRemove(this: ObjectType, entity: T, options?: SaveOptions): Promise; + + /** + * Records the delete date of one or many given entities. + */ + static softRemove(this: ObjectType, entityOrEntities: T|T[], options?: SaveOptions): Promise { + return (this as any).getRepository().softRemove(entityOrEntities as any, options); + } + /** * Inserts a given entity into the database. * Unlike save method executes a primitive operation without cascades, relations and other operations included. diff --git a/src/repository/LiteralRepository.ts b/src/repository/LiteralRepository.ts index c985f5165f..2ddd36e019 100644 --- a/src/repository/LiteralRepository.ts +++ b/src/repository/LiteralRepository.ts @@ -131,8 +131,8 @@ export function createLiteralRepository({ manager, target, queryRunner } return this.manager.findOne(this.getMetadata().target as any, ...args); }, - findOneOrFail(optionsOrConditions?: string | number | Date | ObjectID | FindOptions | FindOptionsWhere, maybeOptions?: FindOptions): Promise { - return this.manager.findOneOrFail(this.getMetadata().target as any, optionsOrConditions as any, maybeOptions); + findOneOrFail(...args: (string | number | Date | ObjectID | FindOptions | FindOptionsWhere | undefined)[]): Promise { + return this.manager.findOneOrFail(this.getMetadata().target as any, ...args); }, observe(optionsOrConditions?: FindOptions | FindOptionsWhere): Observable { diff --git a/src/repository/Repository.ts b/src/repository/Repository.ts index 0969361044..827f51fbeb 100644 --- a/src/repository/Repository.ts +++ b/src/repository/Repository.ts @@ -1,17 +1,17 @@ -import {DeepPartial} from "../common/DeepPartial"; +import {EntityMetadata} from "../metadata/EntityMetadata"; import {ObjectLiteral} from "../common/ObjectLiteral"; -import {ObjectID} from "../driver/mongodb/typings"; -import {EntityManager} from "../entity-manager/EntityManager"; import {FindOptions, FindOptionsWhere} from "../find-options/FindOptions"; -import {EntityMetadata} from "../metadata/EntityMetadata"; +import {DeepPartial} from "../common/DeepPartial"; +import {SaveOptions} from "./SaveOptions"; +import {RemoveOptions} from "./RemoveOptions"; +import {EntityManager} from "../entity-manager/EntityManager"; +import {QueryRunner} from "../query-runner/QueryRunner"; +import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder"; import {DeleteResult} from "../query-builder/result/DeleteResult"; import {UpdateResult} from "../query-builder/result/UpdateResult"; import {InsertResult} from "../query-builder/result/InsertResult"; import {QueryDeepPartialEntity} from "../query-builder/QueryPartialEntity"; -import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder"; -import {QueryRunner} from "../query-runner/QueryRunner"; -import {RemoveOptions} from "./RemoveOptions"; -import {SaveOptions} from "./SaveOptions"; +import {ObjectID} from "../driver/mongodb/typings"; import * as Observable from "zen-observable"; /** @@ -101,7 +101,7 @@ export type Repository = { merge(mergeIntoEntity: Entity, ...entityLikes: DeepPartial[]): Entity /** - * Creates a new entity from the given plan javascript object. If entity already exist in the database, then + * Creates a new entity from the given plain javascript object. If entity already exist in the database, then * it loads it (and everything related to it), replaces all values with the new ones from the given object * and returns this new entity. This new entity is actually a loaded from the db entity with all properties * replaced from the new object. diff --git a/src/schema-builder/MongoSchemaBuilder.ts b/src/schema-builder/MongoSchemaBuilder.ts index 1168c9dd2e..5f580581f9 100644 --- a/src/schema-builder/MongoSchemaBuilder.ts +++ b/src/schema-builder/MongoSchemaBuilder.ts @@ -1,6 +1,6 @@ import {Connection} from "../connection/Connection"; import {SchemaBuilder} from "./SchemaBuilder"; -import {MongoDriver} from "../driver/mongodb/MongoDriver"; +import {MongoQueryRunner} from "../driver/mongodb/MongoQueryRunner"; import {SqlInMemory} from "../driver/SqlInMemory"; import {MongodbIndexOptions} from "../driver/mongodb/typings"; @@ -35,7 +35,7 @@ export class MongoSchemaBuilder implements SchemaBuilder { * Creates complete schemas for the given entity metadatas. */ async build(): Promise { - const queryRunner = (this.connection.driver as MongoDriver).createQueryRunner(); + const queryRunner = this.connection.createQueryRunner() as MongoQueryRunner; const promises: Promise[] = []; this.connection.entityMetadatas.forEach(metadata => { metadata.indices.forEach(index => { diff --git a/src/schema-builder/RdbmsSchemaBuilder.ts b/src/schema-builder/RdbmsSchemaBuilder.ts index 97f7b02455..ce4bb9b010 100644 --- a/src/schema-builder/RdbmsSchemaBuilder.ts +++ b/src/schema-builder/RdbmsSchemaBuilder.ts @@ -10,7 +10,6 @@ import {TableIndex} from "./table/TableIndex"; import {QueryRunner} from "../query-runner/QueryRunner"; import {ColumnMetadata} from "../metadata/ColumnMetadata"; import {EntityMetadata} from "../metadata/EntityMetadata"; -import {PromiseUtils} from "../util/PromiseUtils"; import {Connection} from "../connection/Connection"; import {SchemaBuilder} from "./SchemaBuilder"; import {SqlInMemory} from "../driver/SqlInMemory"; @@ -66,7 +65,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { * Creates complete schemas for the given entity metadatas. */ async build(): Promise { - this.queryRunner = this.connection.createQueryRunner("master"); + this.queryRunner = this.connection.createQueryRunner(); // for sqlite we disable foreign keys constraint check, // because otherwise its not possible to perfrom "re-create" table on schema changes used in sqlite @@ -117,7 +116,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { * Returns sql queries to be executed by schema builder. */ async log(): Promise { - this.queryRunner = this.connection.createQueryRunner("master"); + this.queryRunner = this.connection.createQueryRunner(); try { const tablePaths = this.entityToSyncMetadatas.map(metadata => metadata.tablePath); // TODO: typeorm_metadata table needs only for Views for now. @@ -192,11 +191,10 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { * Drops all (old) foreign keys that exist in the tables, but do not exist in the entity metadata. */ protected async dropOldForeignKeys(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { - + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; // find foreign keys that exist in the schemas but does not exist in the entity metadata const tableForeignKeysToDrop = table.foreignKeys.filter(tableForeignKey => { @@ -206,23 +204,22 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { || (metadataFK.onUpdate && metadataFK.onUpdate !== tableForeignKey.onUpdate); }); if (tableForeignKeysToDrop.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`dropping old foreign keys of ${table.name}: ${tableForeignKeysToDrop.map(dbForeignKey => dbForeignKey.name).join(", ")}`); // drop foreign keys from the database await this.queryRunner.dropForeignKeys(table, tableForeignKeysToDrop); - }); + } } /** * Rename tables */ protected async renameTables(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { - // const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); - - }); + // for (const metadata of this.entityToSyncMetadatas) { + // const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); + // } } /** @@ -231,13 +228,13 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { * Changes only column name. If something besides name was changed, these changes will be ignored. */ protected async renameColumns(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; if (metadata.columns.length !== table.columns.length) - return; + continue; const renamedMetadataColumns = metadata.columns.filter(column => { return !table.columns.find(tableColumn => { @@ -249,7 +246,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { }); if (renamedMetadataColumns.length === 0 || renamedMetadataColumns.length > 1) - return; + continue; const renamedTableColumns = table.columns.filter(tableColumn => { return !metadata.columns.find(column => { @@ -261,21 +258,21 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { }); if (renamedTableColumns.length === 0 || renamedTableColumns.length > 1) - return; + continue; const renamedColumn = renamedTableColumns[0].clone(); renamedColumn.name = renamedMetadataColumns[0].databaseName; this.connection.logger.logSchemaBuild(`renaming column "${renamedTableColumns[0].name}" in to "${renamedColumn.name}"`); await this.queryRunner.renameColumn(table, renamedTableColumns[0], renamedColumn); - }); + } } protected async dropOldIndices(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const dropQueries = table.indices .filter(tableIndex => { @@ -290,7 +287,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { if (indexMetadata.isSpatial !== tableIndex.isSpatial) return true; - if (indexMetadata.isFulltext !== tableIndex.isFulltext) + if (this.connection.driver.isFullTextColumnTypeSupported() && indexMetadata.isFulltext !== tableIndex.isFulltext) return true; if (indexMetadata.columns.length !== tableIndex.columnNames.length) @@ -307,7 +304,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { }); await Promise.all(dropQueries); - }); + } } protected async dropOldChecks(): Promise { @@ -315,39 +312,39 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { if (this.connection.driver instanceof MysqlDriver || this.connection.driver instanceof AuroraDataApiDriver) return; - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const oldChecks = table.checks.filter(tableCheck => { return !metadata.checks.find(checkMetadata => checkMetadata.name === tableCheck.name); }); if (oldChecks.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`dropping old check constraint: ${oldChecks.map(check => `"${check.name}"`).join(", ")} from table "${table.name}"`); await this.queryRunner.dropCheckConstraints(table, oldChecks); - }); + } } protected async dropCompositeUniqueConstraints(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const compositeUniques = table.uniques.filter(tableUnique => { return tableUnique.columnNames.length > 1 && !metadata.uniques.find(uniqueMetadata => uniqueMetadata.name === tableUnique.name); }); if (compositeUniques.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`dropping old unique constraint: ${compositeUniques.map(unique => `"${unique.name}"`).join(", ")} from table "${table.name}"`); await this.queryRunner.dropUniqueConstraints(table, compositeUniques); - }); + } } protected async dropOldExclusions(): Promise { @@ -355,21 +352,21 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { if (!(this.connection.driver instanceof PostgresDriver)) return; - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const oldExclusions = table.exclusions.filter(tableExclusion => { return !metadata.exclusions.find(exclusionMetadata => exclusionMetadata.name === tableExclusion.name); }); if (oldExclusions.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`dropping old exclusion constraint: ${oldExclusions.map(exclusion => `"${exclusion.name}"`).join(", ")} from table "${table.name}"`); await this.queryRunner.dropExclusionConstraints(table, oldExclusions); - }); + } } /** @@ -378,7 +375,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { * Primary key only can be created in conclusion with auto generated column. */ protected async createNewTables(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { // check if table does not exist yet const existTable = this.queryRunner.loadedTables.find(table => { const database = metadata.database && metadata.database !== this.connection.driver.database ? metadata.database : undefined; @@ -388,7 +385,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { return table.name === fullTableName; }); if (existTable) - return; + continue; this.connection.logger.logSchemaBuild(`creating a new table: ${metadata.tablePath}`); @@ -396,11 +393,11 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { const table = Table.create(metadata, this.connection.driver); await this.queryRunner.createTable(table, false, false); this.queryRunner.loadedTables.push(table); - }); + } } protected async createViews(): Promise { - await PromiseUtils.runInSequence(this.viewEntityToSyncMetadatas, async metadata => { + for (const metadata of this.viewEntityToSyncMetadatas) { // check if view does not exist yet const existView = this.queryRunner.loadedViews.find(view => { const database = metadata.database && metadata.database !== this.connection.driver.database ? metadata.database : undefined; @@ -411,7 +408,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { return view.name === fullViewName && viewExpression === metadataExpression; }); if (existView) - return; + continue; this.connection.logger.logSchemaBuild(`creating a new view: ${metadata.tablePath}`); @@ -419,11 +416,11 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { const view = View.create(metadata, this.connection.driver); await this.queryRunner.createView(view); this.queryRunner.loadedViews.push(view); - }); + } } protected async dropOldViews(): Promise { - await PromiseUtils.runInSequence(this.queryRunner.loadedViews, async view => { + for (const view of this.queryRunner.loadedViews) { const existViewMetadata = this.viewEntityToSyncMetadatas.find(metadata => { const database = metadata.database && metadata.database !== this.connection.driver.database ? metadata.database : undefined; const schema = metadata.schema || (this.connection.driver).options.schema; @@ -434,14 +431,14 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { }); if (existViewMetadata) - return; + continue; this.connection.logger.logSchemaBuild(`dropping an old view: ${view.name}`); // drop an old view await this.queryRunner.dropView(view); this.queryRunner.loadedViews.splice(this.queryRunner.loadedViews.indexOf(view), 1); - }); + } } /** @@ -449,22 +446,23 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { * We drop their keys too, since it should be safe. */ protected async dropRemovedColumns(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); - if (!table) return; + if (!table) + continue; // find columns that exist in the database but does not exist in the metadata const droppedTableColumns = table.columns.filter(tableColumn => { return !metadata.columns.find(columnMetadata => columnMetadata.databaseName === tableColumn.name); }); if (droppedTableColumns.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`columns dropped in ${table.name}: ` + droppedTableColumns.map(column => column.name).join(", ")); // drop columns from the database await this.queryRunner.dropColumns(table, droppedTableColumns); - }); + } } /** @@ -472,38 +470,38 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { * Columns are created without keys. */ protected async addNewColumns(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; // find which columns are new const newColumnMetadatas = metadata.columns.filter(columnMetadata => { return !table.columns.find(tableColumn => tableColumn.name === columnMetadata.databaseName); }); if (newColumnMetadatas.length === 0) - return; + continue; // create columns in the database const newTableColumnOptions = this.metadataColumnsToTableColumnOptions(newColumnMetadatas); const newTableColumns = newTableColumnOptions.map(option => new TableColumn(option)); if (newTableColumns.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`new columns added: ` + newColumnMetadatas.map(column => column.databaseName).join(", ")); await this.queryRunner.addColumns(table, newTableColumns); - }); + } } /** * Updates composite primary keys. */ protected async updatePrimaryKeys(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const primaryMetadataColumns = metadata.columns.filter(column => column.isPrimary); const primaryTableColumns = table.columns.filter(column => column.isPrimary); @@ -513,7 +511,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { }); await this.queryRunner.updatePrimaryKeys(table, changedPrimaryColumns); } - }); + } } /** @@ -521,25 +519,31 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { * Still don't create keys. Also we don't touch foreign keys of the changed columns. */ protected async updateExistColumns(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const changedColumns = this.connection.driver.findChangedColumns(table.columns, metadata.columns); if (changedColumns.length === 0) - return; + continue; // drop all foreign keys that point to this column - await PromiseUtils.runInSequence(changedColumns, changedColumn => this.dropColumnReferencedForeignKeys(metadata.tablePath, changedColumn.databaseName)); + for (const changedColumn of changedColumns) { + await this.dropColumnReferencedForeignKeys(metadata.tablePath, changedColumn.databaseName); + } // drop all composite indices related to this column - await PromiseUtils.runInSequence(changedColumns, changedColumn => this.dropColumnCompositeIndices(metadata.tablePath, changedColumn.databaseName)); + for (const changedColumn of changedColumns) { + await this.dropColumnCompositeIndices(metadata.tablePath, changedColumn.databaseName); + } // drop all composite uniques related to this column // Mysql does not support unique constraints. if (!(this.connection.driver instanceof MysqlDriver || this.connection.driver instanceof AuroraDataApiDriver)) { - await PromiseUtils.runInSequence(changedColumns, changedColumn => this.dropColumnCompositeUniques(metadata.tablePath, changedColumn.databaseName)); + for (const changedColumn of changedColumns) { + await this.dropColumnCompositeUniques(metadata.tablePath, changedColumn.databaseName); + } } // generate a map of new/old columns @@ -555,32 +559,32 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { }); if (newAndOldTableColumns.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`columns changed in "${table.name}". updating: ` + changedColumns.map(column => column.databaseName).join(", ")); await this.queryRunner.changeColumns(table, newAndOldTableColumns); - }); + } } /** * Creates composite indices which are missing in db yet. */ protected async createNewIndices(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const newIndices = metadata.indices .filter(indexMetadata => !table.indices.find(tableIndex => tableIndex.name === indexMetadata.name) && indexMetadata.synchronize === true) .map(indexMetadata => TableIndex.create(indexMetadata)); if (newIndices.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`adding new indices ${newIndices.map(index => `"${index.name}"`).join(", ")} in table "${table.name}"`); await this.queryRunner.createIndices(table, newIndices); - }); + } } protected async createNewChecks(): Promise { @@ -588,42 +592,42 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { if (this.connection.driver instanceof MysqlDriver || this.connection.driver instanceof AuroraDataApiDriver) return; - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const newChecks = metadata.checks .filter(checkMetadata => !table.checks.find(tableCheck => tableCheck.name === checkMetadata.name)) .map(checkMetadata => TableCheck.create(checkMetadata)); if (newChecks.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`adding new check constraints: ${newChecks.map(index => `"${index.name}"`).join(", ")} in table "${table.name}"`); await this.queryRunner.createCheckConstraints(table, newChecks); - }); + } } /** * Creates composite uniques which are missing in db yet. */ protected async createCompositeUniqueConstraints(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const compositeUniques = metadata.uniques .filter(uniqueMetadata => uniqueMetadata.columns.length > 1 && !table.uniques.find(tableUnique => tableUnique.name === uniqueMetadata.name)) .map(uniqueMetadata => TableUnique.create(uniqueMetadata)); if (compositeUniques.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`adding new unique constraints: ${compositeUniques.map(unique => `"${unique.name}"`).join(", ")} in table "${table.name}"`); await this.queryRunner.createUniqueConstraints(table, compositeUniques); - }); + } } /** @@ -634,42 +638,42 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { if (!(this.connection.driver instanceof PostgresDriver)) return; - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const newExclusions = metadata.exclusions .filter(exclusionMetadata => !table.exclusions.find(tableExclusion => tableExclusion.name === exclusionMetadata.name)) .map(exclusionMetadata => TableExclusion.create(exclusionMetadata)); if (newExclusions.length === 0) - return; + continue; this.connection.logger.logSchemaBuild(`adding new exclusion constraints: ${newExclusions.map(exclusion => `"${exclusion.name}"`).join(", ")} in table "${table.name}"`); await this.queryRunner.createExclusionConstraints(table, newExclusions); - }); + } } /** * Creates foreign keys which does not exist in the table yet. */ protected async createForeignKeys(): Promise { - await PromiseUtils.runInSequence(this.entityToSyncMetadatas, async metadata => { + for (const metadata of this.entityToSyncMetadatas) { const table = this.queryRunner.loadedTables.find(table => table.name === metadata.tablePath); if (!table) - return; + continue; const newKeys = metadata.foreignKeys.filter(foreignKey => { return !table.foreignKeys.find(dbForeignKey => foreignKeysMatch(dbForeignKey, foreignKey)); }); if (newKeys.length === 0) - return; + continue; const dbForeignKeys = newKeys.map(foreignKeyMetadata => TableForeignKey.create(foreignKeyMetadata)); this.connection.logger.logSchemaBuild(`creating a foreign keys: ${newKeys.map(key => key.name).join(", ")} on table "${table.name}"`); await this.queryRunner.createForeignKeys(table, dbForeignKeys); - }); + } } /** @@ -703,10 +707,10 @@ export class RdbmsSchemaBuilder implements SchemaBuilder { }); if (tablesWithFK.length > 0) { - await PromiseUtils.runInSequence(tablesWithFK, tableWithFK => { + for (const tableWithFK of tablesWithFK) { this.connection.logger.logSchemaBuild(`dropping related foreign keys of ${tableWithFK.name}: ${tableWithFK.foreignKeys.map(foreignKey => foreignKey.name).join(", ")}`); - return this.queryRunner.dropForeignKeys(tableWithFK, tableWithFK.foreignKeys); - }); + await this.queryRunner.dropForeignKeys(tableWithFK, tableWithFK.foreignKeys); + } } } diff --git a/src/schema-builder/options/TableIndexOptions.ts b/src/schema-builder/options/TableIndexOptions.ts index c75228e2fd..b37be3d790 100644 --- a/src/schema-builder/options/TableIndexOptions.ts +++ b/src/schema-builder/options/TableIndexOptions.ts @@ -30,10 +30,10 @@ export interface TableIndexOptions { /** * The FULLTEXT modifier indexes the entire column and does not allow prefixing. - * Works only in MySQL. + * Supported only in MySQL & SAP HANA. */ isFulltext?: boolean; - + /** * Fulltext parser. * Works only in MySQL. @@ -45,4 +45,4 @@ export interface TableIndexOptions { */ where?: string; -} \ No newline at end of file +} diff --git a/src/subscriber/Broadcaster.ts b/src/subscriber/Broadcaster.ts index e97d9a8bc1..0dc3aaf326 100644 --- a/src/subscriber/Broadcaster.ts +++ b/src/subscriber/Broadcaster.ts @@ -88,8 +88,8 @@ export class Broadcaster { connection: this.queryRunner.connection, queryRunner: this.queryRunner, manager: this.queryRunner.manager, - metadata: metadata, entity: entity, + metadata: metadata, databaseEntity: databaseEntity, updatedColumns: updatedColumns || [], updatedRelations: updatedRelations || [] @@ -129,8 +129,8 @@ export class Broadcaster { connection: this.queryRunner.connection, queryRunner: this.queryRunner, manager: this.queryRunner.manager, - metadata: metadata, entity: entity, + metadata: metadata, databaseEntity: databaseEntity, entityId: metadata.getEntityIdMixedMap(databaseEntity) }); @@ -209,8 +209,8 @@ export class Broadcaster { connection: this.queryRunner.connection, queryRunner: this.queryRunner, manager: this.queryRunner.manager, - metadata: metadata, entity: entity, + metadata: metadata, databaseEntity: databaseEntity, updatedColumns: updatedColumns || [], updatedRelations: updatedRelations || [] @@ -251,8 +251,8 @@ export class Broadcaster { connection: this.queryRunner.connection, queryRunner: this.queryRunner, manager: this.queryRunner.manager, - metadata: metadata, entity: entity, + metadata: metadata, databaseEntity: databaseEntity, entityId: metadata.getEntityIdMixedMap(databaseEntity) }); diff --git a/src/subscriber/event/InsertEvent.ts b/src/subscriber/event/InsertEvent.ts index 8b5a117222..24e94f2845 100644 --- a/src/subscriber/event/InsertEvent.ts +++ b/src/subscriber/event/InsertEvent.ts @@ -1,7 +1,7 @@ -import {EntityMetadata} from "../.."; import {EntityManager} from "../../entity-manager/EntityManager"; import {Connection} from "../../connection/Connection"; import {QueryRunner} from "../../query-runner/QueryRunner"; +import { EntityMetadata } from "../../metadata/EntityMetadata"; /** * InsertEvent is an object that broadcaster sends to the entity subscriber when entity is inserted to the database. @@ -26,13 +26,13 @@ export interface InsertEvent { manager: EntityManager; /** - * Entity metadata of the inserted entity. + * Inserting event. */ - metadata: EntityMetadata; + entity: Entity; /** - * Inserting event. + * Metadata of the entity. */ - entity: Entity; + metadata: EntityMetadata; } diff --git a/src/subscriber/event/RemoveEvent.ts b/src/subscriber/event/RemoveEvent.ts index d0666ab7f8..b74957b4e7 100644 --- a/src/subscriber/event/RemoveEvent.ts +++ b/src/subscriber/event/RemoveEvent.ts @@ -1,7 +1,7 @@ -import {EntityMetadata} from "../.."; import {EntityManager} from "../../entity-manager/EntityManager"; import {Connection} from "../../connection/Connection"; import {QueryRunner} from "../../query-runner/QueryRunner"; +import { EntityMetadata } from "../../metadata/EntityMetadata"; /** * RemoveEvent is an object that broadcaster sends to the entity subscriber when entity is being removed to the database. @@ -25,17 +25,17 @@ export interface RemoveEvent { */ manager: EntityManager; - /** - * Entity metadata of the removed entity. - */ - metadata: EntityMetadata; - /** * Entity that is being removed. * This may absent if entity is removed without being loaded (for examples by cascades). */ entity?: Entity; + /** + * Metadata of the entity. + */ + metadata: EntityMetadata; + /** * Database representation of entity that is being removed. */ diff --git a/src/subscriber/event/UpdateEvent.ts b/src/subscriber/event/UpdateEvent.ts index 55fa53df18..559559e0be 100644 --- a/src/subscriber/event/UpdateEvent.ts +++ b/src/subscriber/event/UpdateEvent.ts @@ -1,9 +1,9 @@ -import {EntityMetadata} from "../.."; import {ColumnMetadata} from "../../metadata/ColumnMetadata"; import {RelationMetadata} from "../../metadata/RelationMetadata"; import {EntityManager} from "../../entity-manager/EntityManager"; import {QueryRunner} from "../../query-runner/QueryRunner"; import {Connection} from "../../connection/Connection"; +import { EntityMetadata } from "../../metadata/EntityMetadata"; /** * UpdateEvent is an object that broadcaster sends to the entity subscriber when entity is being updated in the database. diff --git a/src/util/DirectoryExportedClassesLoader.ts b/src/util/DirectoryExportedClassesLoader.ts index 0456fd3749..3e64efe1f5 100644 --- a/src/util/DirectoryExportedClassesLoader.ts +++ b/src/util/DirectoryExportedClassesLoader.ts @@ -1,11 +1,11 @@ +import glob from "glob"; import {PlatformTools} from "../platform/PlatformTools"; import {EntitySchema} from "../index"; import {Logger} from "../logger/Logger"; - /** * Loads all exported classes from the given directory. */ -export function importClassesFromDirectories(logger: Logger, directories: string[], formats = [".js", ".ts"]): Function[] { +export function importClassesFromDirectories(logger: Logger, directories: string[], formats = [".js", ".cjs", ".ts"]): Function[] { const logLevel = "info"; const classesNotFoundMessage = "No classes were found using the provided glob pattern: "; @@ -25,7 +25,7 @@ export function importClassesFromDirectories(logger: Logger, directories: string } const allFiles = directories.reduce((allDirs, dir) => { - return allDirs.concat(PlatformTools.load("glob").sync(PlatformTools.pathNormalize(dir))); + return allDirs.concat(glob.sync(PlatformTools.pathNormalize(dir))); }, [] as string[]); if (directories.length > 0 && allFiles.length === 0) { @@ -38,7 +38,7 @@ export function importClassesFromDirectories(logger: Logger, directories: string const dtsExtension = file.substring(file.length - 5, file.length); return formats.indexOf(PlatformTools.pathExtname(file)) !== -1 && dtsExtension !== ".d.ts"; }) - .map(file => PlatformTools.load(PlatformTools.pathResolve(file))); + .map(file => require(PlatformTools.pathResolve(file))); return loadFileClasses(dirs, []); } @@ -49,10 +49,10 @@ export function importClassesFromDirectories(logger: Logger, directories: string export function importJsonsFromDirectories(directories: string[], format = ".json"): any[] { const allFiles = directories.reduce((allDirs, dir) => { - return allDirs.concat(PlatformTools.load("glob").sync(PlatformTools.pathNormalize(dir))); + return allDirs.concat(glob.sync(PlatformTools.pathNormalize(dir))); }, [] as string[]); return allFiles .filter(file => PlatformTools.pathExtname(file) === format) - .map(file => PlatformTools.load(PlatformTools.pathResolve(file))); + .map(file => require(PlatformTools.pathResolve(file))); } diff --git a/src/util/OrmUtils.ts b/src/util/OrmUtils.ts index 69aa6cb7be..9fcaad1b6a 100644 --- a/src/util/OrmUtils.ts +++ b/src/util/OrmUtils.ts @@ -74,7 +74,7 @@ export class OrmUtils { if (this.isObject(target) && this.isObject(source)) { for (const key in source) { const value = source[key]; - if (value instanceof Promise) + if (key === "__proto__" || value instanceof Promise) continue; if (this.isObject(value) @@ -100,7 +100,7 @@ export class OrmUtils { * * @see http://stackoverflow.com/a/1144249 */ - static deepCompare(...args: any[]) { + static deepCompare(...args: any[]): boolean { let i: any, l: any, leftChain: any, rightChain: any; if (arguments.length < 1) { @@ -121,6 +121,26 @@ export class OrmUtils { return true; } + /** + * Check if two entity-id-maps are the same + */ + static compareIds(firstId: ObjectLiteral|undefined, secondId: ObjectLiteral|undefined): boolean { + if (firstId === undefined || firstId === null || secondId === undefined || secondId === null) + return false; + + // Optimized version for the common case + if ( + ((typeof firstId.id === "string" && typeof secondId.id === "string") || + (typeof firstId.id === "number" && typeof secondId.id === "number")) && + Object.keys(firstId).length === 1 && + Object.keys(secondId).length === 1 + ) { + return firstId.id === secondId.id; + } + + return OrmUtils.deepCompare(firstId, secondId); + } + /** * Transforms given value into boolean value. */ diff --git a/src/util/PromiseUtils.ts b/src/util/PromiseUtils.ts deleted file mode 100644 index 326d6c4403..0000000000 --- a/src/util/PromiseUtils.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Utils to help to work with Promise objects. - */ -export class PromiseUtils { - - /** - * Creates a new promise with resolved value used for lazy relations. - */ - static create(value: any) { - const promise = Promise.resolve(value); - (promise as any)["__value__"] = value; - return promise; - } - - /** - * If given value is a promise created by "create" method this method gets its value. - * If given value is not a promise then given value is returned back. - */ - static extractValue(object: any) { - if (object instanceof Promise && (object as any)["__value__"]) - return (object as any)["__value__"]; - - return object; - } - - /** - * Runs given callback that returns promise for each item in the given collection in order. - * Operations executed after each other, right after previous promise being resolved. - */ - static runInSequence(collection: T[], callback: (item: T) => Promise): Promise { - const results: U[] = []; - return collection.reduce((promise, item) => { - return promise.then(() => { - return callback(item); - }).then(result => { - results.push(result); - }); - }, Promise.resolve()).then(() => { - return results; - }); - } - - /** - * Returns a promise that is fulfilled with an array of promise state snapshots, - * but only after all the original promises have settled, i.e. become either fulfilled or rejected. - */ - static settle(promises: Promise[]) { - return Promise.all(promises.map(p => Promise.resolve(p).then(v => ({ - state: "fulfilled", - value: v, - }), r => ({ - state: "rejected", - reason: r, - })))).then((results: any[]): any => { - const rejected = results.find(result => result.state === "rejected"); - if (rejected) - return Promise.reject(rejected.reason); - - return results.map(result => result.value); - }); - } - -} \ No newline at end of file diff --git a/src/util/StringUtils.ts b/src/util/StringUtils.ts index 808554c60e..54f1a1a395 100644 --- a/src/util/StringUtils.ts +++ b/src/util/StringUtils.ts @@ -1,4 +1,4 @@ -import * as shajs from "sha.js"; +import shajs from "sha.js"; /** * Converts string into camelCase. diff --git a/test/core/column-kinds/create-date-column/create-date-column.ts b/test/core/column-kinds/create-date-column/create-date-column.ts new file mode 100644 index 0000000000..6081b2b921 --- /dev/null +++ b/test/core/column-kinds/create-date-column/create-date-column.ts @@ -0,0 +1,96 @@ +import { expect } from "chai"; +import "reflect-metadata"; +import { Connection } from "../../../../src"; +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases, + sleep +} from "../../../utils/test-utils"; +import { Post } from "./entity/Post"; + +describe("column kinds > create date column", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("create date column should automatically be set by a database", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // load and check if createdAt is a date (generated by db) + const loadedPost = await postRepository.findOne(); + expect(loadedPost).to.be.not.empty; + expect(loadedPost!.title).to.be.eql("Post"); + expect(loadedPost!.createdAt).to.be.instanceOf(Date); + }))); + + it("create date column can also be manually set by user", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + const createdAt = new Date(Date.parse("2020-01-01T00:00:00+0000")); + + // save a new post + const post = new Post(); + post.title = "Post"; + post.createdAt = createdAt; + await postRepository.save(post); + + // load and check if createdAt was a value set by us + const loadedPost = await postRepository.findOne(); + expect(loadedPost).to.be.not.empty; + expect(loadedPost!.title).to.be.eql("Post"); + expect(loadedPost!.createdAt).to.be.eql(createdAt); + + }))); + + it("create date column should not be updated automatically on every change", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // load to get created date we had after first save + const loadedPostBeforeUpdate = await postRepository.findOne(); + + // wait a second + await sleep(1000); + + // create post once again + post.title = "Updated Title"; + await postRepository.save(post); + + // check if date was created + const loadedPostAfterUpdate = await postRepository.findOne(); + expect(loadedPostAfterUpdate!.createdAt.toString()).to.be.eql(loadedPostBeforeUpdate!.createdAt.toString()); + }))); + + it("create date column should set a custom date when specified", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // create post once again + const createdAt = new Date(Date.parse("2020-01-01T00:00:00+0000")); + post.title = "Updated Title"; + post.createdAt = createdAt; + await postRepository.save(post); + + // check if date was created + const loadedPost = await postRepository.findOne(); + expect(loadedPost!.createdAt).to.be.eql(createdAt); + }))); +}); diff --git a/test/core/column-kinds/create-date-column/entity/Post.ts b/test/core/column-kinds/create-date-column/entity/Post.ts new file mode 100644 index 0000000000..ddc2b7baa9 --- /dev/null +++ b/test/core/column-kinds/create-date-column/entity/Post.ts @@ -0,0 +1,15 @@ +import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from "../../../../../src"; + +@Entity() +export class Post { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + title: string; + + @CreateDateColumn() + createdAt: Date; + +} diff --git a/test/core/column-kinds/geometry-column/entity/Feature.ts b/test/core/column-kinds/geometry-column/entity/Feature.ts new file mode 100644 index 0000000000..3bc959fae3 --- /dev/null +++ b/test/core/column-kinds/geometry-column/entity/Feature.ts @@ -0,0 +1,29 @@ +import { Column, Entity, PrimaryGeneratedColumn } from "../../../../../src"; + +@Entity() +export class FeatureWithoutSRID { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + name: string; + + @Column({ type: "geometry" }) + shape: string; + +} + +@Entity() +export class FeatureWithSRID { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + name: string; + + @Column({ type: "geometry", srid: 2326 }) + shape: string; + +} diff --git a/test/core/column-kinds/geometry-column/geometry-column.ts b/test/core/column-kinds/geometry-column/geometry-column.ts new file mode 100644 index 0000000000..f46fb9e016 --- /dev/null +++ b/test/core/column-kinds/geometry-column/geometry-column.ts @@ -0,0 +1,108 @@ +import { expect } from "chai"; +import "reflect-metadata"; +import { Connection } from "../../../../src"; +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases, +} from "../../../utils/test-utils"; +import { FeatureWithoutSRID, FeatureWithSRID } from "./entity/Feature"; + +describe("column kinds > geometry column", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + enabledDrivers: ["mssql"] + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + + + it("geometry column with SRID defined should be saved without error for valid WKT input", () => Promise.all(connections.map(async connection => { + const featureRepository = connection.getRepository(FeatureWithSRID); + + // save a new feature + const feature = new FeatureWithSRID(); + feature.name = "feature"; + feature.shape = "POINT (828365.16700000037 823377.14699999988)"; + await featureRepository.save(feature); + + // load and check if createdAt was a value set by us + const loadedfeature = await featureRepository.findOne(); + expect(loadedfeature).to.be.not.empty; + expect(loadedfeature!.name).to.be.eql("feature"); + expect(loadedfeature!.shape).to.be.eql("POINT (828365.16700000037 823377.14699999988)"); + + }))); + + it("geometry column with SRID defined should be updated without error for valid WKT input", () => Promise.all(connections.map(async connection => { + const featureRepository = connection.getRepository(FeatureWithSRID); + + // save a new feature + const feature = new FeatureWithSRID(); + feature.name = "feature"; + feature.shape = "POINT (828365.16700000037 823377.14699999988)"; + await featureRepository.save(feature); + + // load and check if createdAt was a value set by us + const loadedfeature = await featureRepository.findOne(); + expect(loadedfeature).to.be.not.empty; + expect(loadedfeature!.name).to.be.eql("feature"); + expect(loadedfeature!.shape).to.be.eql("POINT (828365.16700000037 823377.14699999988)"); + + feature.shape = "POINT (728365.16700000037 723377.14699999988)"; + await featureRepository.save(feature); + + // load and check if createdAt is a date (generated by db) + const updatedfeature = await featureRepository.findOne(); + expect(updatedfeature).to.be.not.empty; + expect(updatedfeature!.name).to.be.eql("feature"); + expect(updatedfeature!.shape).to.be.eql("POINT (728365.16700000037 723377.14699999988)"); + + }))); + + it("geometry column with no SRID should be saved without error for valid WKT input", () => Promise.all(connections.map(async connection => { + const featureRepository = connection.getRepository(FeatureWithoutSRID); + + // save a new feature + const feature = new FeatureWithoutSRID(); + feature.name = "feature"; + feature.shape = "POINT (0 0)"; + await featureRepository.save(feature); + + // load and check if createdAt is a date (generated by db) + const loadedfeature = await featureRepository.findOne(); + expect(loadedfeature).to.be.not.empty; + expect(loadedfeature!.name).to.be.eql("feature"); + expect(loadedfeature!.shape).to.be.eql("POINT (0 0)"); + }))); + + it("geometry column with no SRID should be updated without error for valid WKT input", () => Promise.all(connections.map(async connection => { + const featureRepository = connection.getRepository(FeatureWithoutSRID); + + // save a new feature + const feature = new FeatureWithoutSRID(); + feature.name = "feature"; + feature.shape = "POINT (0 0)"; + await featureRepository.save(feature); + + // load and check if createdAt is a date (generated by db) + const loadedfeature = await featureRepository.findOne(); + expect(loadedfeature).to.be.not.empty; + expect(loadedfeature!.name).to.be.eql("feature"); + expect(loadedfeature!.shape).to.be.eql("POINT (0 0)"); + + feature.shape = "POINT (0.5 0.5)"; + await featureRepository.save(feature); + + // load and check if createdAt is a date (generated by db) + const updatedfeature = await featureRepository.findOne(); + expect(updatedfeature).to.be.not.empty; + expect(updatedfeature!.name).to.be.eql("feature"); + expect(updatedfeature!.shape).to.be.eql("POINT (0.5 0.5)"); + + }))); + +}); diff --git a/test/core/column-kinds/update-date-column/entity/Post.ts b/test/core/column-kinds/update-date-column/entity/Post.ts new file mode 100644 index 0000000000..2a1908e2cd --- /dev/null +++ b/test/core/column-kinds/update-date-column/entity/Post.ts @@ -0,0 +1,15 @@ +import { Column, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "../../../../../src"; + +@Entity() +export class Post { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + title: string; + + @UpdateDateColumn() + updatedAt: Date; + +} diff --git a/test/core/column-kinds/update-date-column/update-date-column.ts b/test/core/column-kinds/update-date-column/update-date-column.ts new file mode 100644 index 0000000000..1b1561c789 --- /dev/null +++ b/test/core/column-kinds/update-date-column/update-date-column.ts @@ -0,0 +1,115 @@ +import { expect } from "chai"; +import "reflect-metadata"; +import { Connection } from "../../../../src"; +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases, + sleep +} from "../../../utils/test-utils"; +import { Post } from "./entity/Post"; + +describe("column kinds > update date column", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("update date column should automatically be set by a database", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // load and check if updatedAt is a date (generated by db) + const loadedPost = await postRepository.findOne(); + expect(loadedPost).to.be.not.empty; + expect(loadedPost!.title).to.be.eql("Post"); + expect(loadedPost!.updatedAt).to.be.instanceOf(Date); + }))); + + it("update column should not update if no changes were detected", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // update post once again + const loadedPost1 = await postRepository.findOneOrFail(); + await postRepository.save(loadedPost1); + + // load and check if version was a value set by us + const loadedPost2 = await postRepository.findOne(); + + // make sure version is the same + expect(loadedPost2!.title).to.be.eql("Post"); + expect(loadedPost2!.updatedAt).to.be.eql(loadedPost1.updatedAt); + }))); + + it("update date column can also be manually set by user", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + const updatedAt = new Date(Date.parse("2020-01-01T00:00:00+0000")); + + // save a new post + const post = new Post(); + post.title = "Post"; + post.updatedAt = updatedAt; + await postRepository.save(post); + + // load and check if updatedAt was a value set by us + const loadedPost = await postRepository.findOne(); + expect(loadedPost).to.be.not.empty; + expect(loadedPost!.title).to.be.eql("Post"); + expect(loadedPost!.updatedAt).to.be.eql(updatedAt); + }))); + + it("update date column should be updated automatically on every change", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // load to get updated date we had after first save + const loadedPostBeforeUpdate = await postRepository.findOne(); + + // wait a second + await sleep(1000); + + // update post once again + post.title = "Updated Title"; + await postRepository.save(post); + + // check if date was updated + const loadedPostAfterUpdate = await postRepository.findOne(); + expect(loadedPostAfterUpdate!.updatedAt.toString()).to.be.not.eql(loadedPostBeforeUpdate!.updatedAt.toString()); + }))); + + it("update date column should set a custom date when specified", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // update post once again + const updatedAt = new Date(Date.parse("2020-01-01T00:00:00+0000")); + post.title = "Updated Title"; + post.updatedAt = updatedAt; + await postRepository.save(post); + + // check if date was updated + const loadedPost = await postRepository.findOne(); + expect(loadedPost!.updatedAt).to.be.eql(updatedAt); + }))); +}); diff --git a/test/core/column-kinds/version-column/entity/Post.ts b/test/core/column-kinds/version-column/entity/Post.ts new file mode 100644 index 0000000000..5373c7693d --- /dev/null +++ b/test/core/column-kinds/version-column/entity/Post.ts @@ -0,0 +1,15 @@ +import { Column, Entity, PrimaryGeneratedColumn, VersionColumn } from "../../../../../src"; + +@Entity() +export class Post { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + title: string; + + @VersionColumn() + version: number; + +} diff --git a/test/core/column-kinds/version-column/version-column.ts b/test/core/column-kinds/version-column/version-column.ts new file mode 100644 index 0000000000..d3da25e465 --- /dev/null +++ b/test/core/column-kinds/version-column/version-column.ts @@ -0,0 +1,109 @@ +import { expect } from "chai"; +import "reflect-metadata"; +import { Connection } from "../../../../src"; +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases, + sleep +} from "../../../utils/test-utils"; +import { Post } from "./entity/Post"; + +describe("column kinds > version column", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("version column should automatically be set by a database", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // load and check if version is a date (generated by db) + const loadedPost = await postRepository.findOne(); + expect(loadedPost).to.be.not.empty; + expect(loadedPost!.title).to.be.eql("Post"); + expect(loadedPost!.version).to.be.eql(1); + }))); + + it("version column should not update version if no changes were detected", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // update post once again + const loadedPost1 = await postRepository.findOneOrFail(); + await postRepository.save(loadedPost1); + + // load and check if version was a value set by us + const loadedPost2 = await postRepository.findOne(); + + // make sure version is the same + expect(loadedPost2!.title).to.be.eql("Post"); + expect(loadedPost2!.version).to.be.eql(1); + }))); + + it("version column can also be manually set by user", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + post.version = 5; + await postRepository.save(post); + + // load and check if version was a value set by us + const loadedPost = await postRepository.findOne(); + expect(loadedPost).to.be.not.empty; + expect(loadedPost!.title).to.be.eql("Post"); + expect(loadedPost!.version).to.be.eql(5); + }))); + + it("version column should be updated automatically on every change", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // wait a second + await sleep(1000); + + // update post once again + post.title = "Updated Title"; + await postRepository.save(post); + + // check if date was updated + const loadedPostAfterUpdate = await postRepository.findOne(); + expect(loadedPostAfterUpdate!.version).to.be.eql(2); + }))); + + it("version column should set a custom value when specified", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new post + const post = new Post(); + post.title = "Post"; + await postRepository.save(post); + + // update post once again + post.title = "Updated Title"; + post.version = 6; + await postRepository.save(post); + + // check if date was updated + const loadedPost = await postRepository.findOne(); + expect(loadedPost!.version).to.be.eql(6); + }))); +}); diff --git a/test/functional/cache/provider/MockQueryResultCache.ts b/test/functional/cache/provider/MockQueryResultCache.ts index 1d2993911f..de1335b089 100644 --- a/test/functional/cache/provider/MockQueryResultCache.ts +++ b/test/functional/cache/provider/MockQueryResultCache.ts @@ -229,7 +229,7 @@ export class MockQueryResultCache implements QueryResultCache { if (queryRunner) return queryRunner; - return this.connection.createQueryRunner("master"); + return this.connection.createQueryRunner(); } } diff --git a/test/functional/columns/readonly/entity/Post.ts b/test/functional/columns/readonly/entity/Post.ts index 775d859fe2..9db6d58729 100644 --- a/test/functional/columns/readonly/entity/Post.ts +++ b/test/functional/columns/readonly/entity/Post.ts @@ -1,4 +1,6 @@ -import {Column, Entity, PrimaryGeneratedColumn} from "../../../../../src"; +import {Entity} from "../../../../../src/decorator/entity/Entity"; +import {Column} from "../../../../../src/decorator/columns/Column"; +import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn"; @Entity() export class Post { @@ -15,4 +17,4 @@ export class Post { @Column({ readonly: true }) authorName: string; -} \ No newline at end of file +} diff --git a/test/functional/connection-manager/connection-manager.ts b/test/functional/connection-manager/connection-manager.ts index 6cd86c9d4d..acc378af99 100644 --- a/test/functional/connection-manager/connection-manager.ts +++ b/test/functional/connection-manager/connection-manager.ts @@ -7,6 +7,12 @@ import {PrimaryGeneratedColumn} from "../../../src/decorator/columns/PrimaryGene import {Column} from "../../../src/decorator/columns/Column"; import {Entity} from "../../../src/decorator/entity/Entity"; +// Uncomment when testing the aurora data API driver +// import {AuroraDataApiDriver} from "../../../src/driver/aurora-data-api/AuroraDataApiDriver"; +// import {AuroraDataApiConnectionOptions} from "../../../src/driver/aurora-data-api/AuroraDataApiConnectionOptions"; +// import {AuroraDataApiPostgresDriver} from "../../../src/driver/postgres/PostgresDriver"; +// import {AuroraDataApiPostgresConnectionOptions} from "../../../src/driver/aurora-data-api-pg/AuroraDataApiPostgresConnectionOptions"; + describe("ConnectionManager", () => { @Entity() @@ -68,6 +74,41 @@ describe("ConnectionManager", () => { connection.driver.should.be.instanceOf(MysqlDriver); connection.isConnected.should.be.true; await connection.close(); + + it("should create a aurora connection when aurora-data-api driver is specified", async () => { + const options = setupSingleTestingConnection("aurora-data-api", { + name: "aurora-data-api", + dropSchema: false, + schemaCreate: false, + enabledDrivers: ["aurora-data-api"] + }); + const connectionManager = new ConnectionManager(); + const connection = connectionManager.create(options!); + await connection.connect(); + connection.name.should.contain("aurora-data-api"); + connection.driver.should.be.instanceOf(AuroraDataApiDriver); + connection.isConnected.should.be.true; + const serviceConfigOptions = (connection.options as AuroraDataApiConnectionOptions).serviceConfigOptions; + expect(serviceConfigOptions).to.include({ maxRetries: 3, region: "us-east-1" }); + await connection.close(); + }); + + it("should create a aurora connection when aurora-data-api-pg driver is specified", async () => { + const options = setupSingleTestingConnection("aurora-data-api-pg", { + name: "aurora-data-api-pg", + dropSchema: false, + schemaCreate: false, + enabledDrivers: ["aurora-data-api-pg"] + }); + const connectionManager = new ConnectionManager(); + const connection = connectionManager.create(options!); + await connection.connect(); + connection.name.should.contain("aurora-data-api-pg"); + connection.driver.should.be.instanceOf(AuroraDataApiPostgresDriver); + connection.isConnected.should.be.true; + const serviceConfigOptions = (connection.options as AuroraDataApiPostgresConnectionOptions).serviceConfigOptions; + expect(serviceConfigOptions).to.include({ maxRetries: 3, region: "us-east-1" }); + await connection.close(); }); /!* it("should create a postgres connection when postgres driver is specified AND connect to it", async () => { diff --git a/test/functional/connection-options-reader/configs/sqlite-memory.ts b/test/functional/connection-options-reader/configs/sqlite-memory.ts index 243dd45cef..81907c198e 100644 --- a/test/functional/connection-options-reader/configs/sqlite-memory.ts +++ b/test/functional/connection-options-reader/configs/sqlite-memory.ts @@ -6,4 +6,8 @@ module.exports = [{ type: "sqlite", name: "memory", database: ":memory:", +}, { + type: "better-sqlite3", + name: "memory2", + database: ":memory:", }]; \ No newline at end of file diff --git a/test/functional/connection/connection.ts b/test/functional/connection/connection.ts index dd14d9e7f6..f21414f46c 100644 --- a/test/functional/connection/connection.ts +++ b/test/functional/connection/connection.ts @@ -14,7 +14,6 @@ import {NoConnectionForRepositoryError} from "../../../src/error/NoConnectionFor import {CannotGetEntityManagerNotConnectedError} from "../../../src/error/CannotGetEntityManagerNotConnectedError"; import {ConnectionOptions} from "../../../src/connection/ConnectionOptions"; import {PostgresConnectionOptions} from "../../../src/driver/postgres/PostgresConnectionOptions"; -import {PromiseUtils} from "../../../src/util/PromiseUtils"; describe("Connection", () => { // const resourceDir = __dirname + "/../../../../../test/functional/connection/"; @@ -258,7 +257,7 @@ describe("Connection", () => { after(() => closeTestingConnections(connections)); it("should not interfere with each other", async () => { - await PromiseUtils.runInSequence(connections, c => c.synchronize()); + await Promise.all(connections.map(c => c.synchronize())); await closeTestingConnections(connections); const connections1 = await createTestingConnections({ name: "test", diff --git a/test/functional/database-schema/column-collation/sqlite/column-collation-sqlite.ts b/test/functional/database-schema/column-collation/sqlite/column-collation-sqlite.ts index cfd415258e..869aa9785e 100644 --- a/test/functional/database-schema/column-collation/sqlite/column-collation-sqlite.ts +++ b/test/functional/database-schema/column-collation/sqlite/column-collation-sqlite.ts @@ -10,7 +10,7 @@ describe.skip("database schema > column collation > sqlite", () => { before(async () => { connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"], + enabledDrivers: ["sqlite", "better-sqlite3"], }); }); beforeEach(() => reloadTestingDatabases(connections)); diff --git a/test/functional/database-schema/column-length/sqlite/column-length-sqlite..ts b/test/functional/database-schema/column-length/sqlite/column-length-sqlite..ts index deffdbd3aa..64a9d7f8fe 100644 --- a/test/functional/database-schema/column-length/sqlite/column-length-sqlite..ts +++ b/test/functional/database-schema/column-length/sqlite/column-length-sqlite..ts @@ -10,7 +10,7 @@ describe("database schema > column length > sqlite", () => { before(async () => { connections = await createTestingConnections({ entities: [Post], - enabledDrivers: ["sqlite"], + enabledDrivers: ["sqlite", "better-sqlite3"], }); }); beforeEach(() => reloadTestingDatabases(connections)); diff --git a/test/functional/database-schema/column-types/mssql/column-types-mssql.ts b/test/functional/database-schema/column-types/mssql/column-types-mssql.ts index b7afa047d3..97a2610bbc 100644 --- a/test/functional/database-schema/column-types/mssql/column-types-mssql.ts +++ b/test/functional/database-schema/column-types/mssql/column-types-mssql.ts @@ -48,9 +48,9 @@ describe("database schema > column types > mssql", () => { // https://github.com post.nchar = "A"; post.nvarchar = "This is nvarchar"; post.ntext = "This is ntext"; - post.binary = new Buffer("A"); - post.varbinary = new Buffer("B"); - post.image = new Buffer("This is image"); + post.binary = Buffer.from("A"); + post.varbinary = Buffer.from("B"); + post.image = Buffer.from("This is image"); post.dateObj = new Date(); post.date = "2017-06-21"; post.datetime = new Date(); @@ -182,8 +182,8 @@ describe("database schema > column types > mssql", () => { // https://github.com post.varchar = "This is varchar"; post.nchar = "AAA"; post.nvarchar = "This is nvarchar"; - post.binary = new Buffer("AAAAA"); - post.varbinary = new Buffer("BBBBB"); + post.binary = Buffer.from("AAAAA"); + post.varbinary = Buffer.from("BBBBB"); post.datetime2 = new Date(); post.time = new Date(); post.datetimeoffset = new Date(); @@ -252,7 +252,7 @@ describe("database schema > column types > mssql", () => { // https://github.com post.id = 1; post.name = "Post"; post.bit = true; - post.binary = new Buffer("A"); + post.binary = Buffer.from("A"); post.datetime = new Date(); post.datetime.setMilliseconds(0); // set milliseconds to zero because the SQL Server datetime type only has a 1/300 ms (~3.33̅ ms) resolution await postRepository.save(post); diff --git a/test/functional/database-schema/column-types/mysql/column-types-mysql.ts b/test/functional/database-schema/column-types/mysql/column-types-mysql.ts index 287a81b406..5928c7bead 100644 --- a/test/functional/database-schema/column-types/mysql/column-types-mysql.ts +++ b/test/functional/database-schema/column-types/mysql/column-types-mysql.ts @@ -61,12 +61,12 @@ describe("database schema > column types > mysql", () => { post.timestamp.setMilliseconds(0); // set milliseconds to zero, because if datetime type specified without precision, milliseconds won't save in database post.time = "15:30:00"; post.year = 2017; - post.binary = new Buffer("A"); - post.varbinary = new Buffer("B"); - post.blob = new Buffer("This is blob"); - post.tinyblob = new Buffer("This is tinyblob"); - post.mediumblob = new Buffer("This is mediumblob"); - post.longblob = new Buffer("This is longblob"); + post.binary = Buffer.from("A"); + post.varbinary = Buffer.from("B"); + post.blob = Buffer.from("This is blob"); + post.tinyblob = Buffer.from("This is tinyblob"); + post.mediumblob = Buffer.from("This is mediumblob"); + post.longblob = Buffer.from("This is longblob"); post.geometry = "POINT(1 1)"; post.point = "POINT(1 1)"; post.linestring = "LINESTRING(0 0,1 1,2 2)"; @@ -278,7 +278,7 @@ describe("database schema > column types > mysql", () => { post.id = 1; post.name = "Post"; post.boolean = true; - post.blob = new Buffer("A"); + post.blob = Buffer.from("A"); post.datetime = new Date(); post.datetime.setMilliseconds(0); // set milliseconds to zero, because if datetime type specified without precision, milliseconds won't save in database await postRepository.save(post); diff --git a/test/functional/database-schema/column-types/oracle/column-types-oracle.ts b/test/functional/database-schema/column-types/oracle/column-types-oracle.ts index e07dd3795a..2a70cfef09 100644 --- a/test/functional/database-schema/column-types/oracle/column-types-oracle.ts +++ b/test/functional/database-schema/column-types/oracle/column-types-oracle.ts @@ -43,7 +43,7 @@ describe("database schema > column types > oracle", () => { post.varchar2 = "This is varchar2"; post.nvarchar2 = "This is nvarchar2"; post.long = "This is long"; - post.raw = new Buffer("This is raw"); + post.raw = Buffer.from("This is raw"); post.dateObj = new Date(); post.date = "2017-06-21"; post.timestamp = new Date(); @@ -52,7 +52,7 @@ describe("database schema > column types > oracle", () => { post.timestampWithTimeZone.setMilliseconds(0); post.timestampWithLocalTimeZone = new Date(); post.timestampWithLocalTimeZone.setMilliseconds(0); - post.blob = new Buffer("This is blob"); + post.blob = Buffer.from("This is blob"); post.clob = "This is clob"; post.nclob = "This is nclob"; post.simpleArray = ["A", "B", "C"]; @@ -137,7 +137,7 @@ describe("database schema > column types > oracle", () => { post.nchar = "AAA"; post.varchar2 = "This is varchar"; post.nvarchar2 = "This is nvarchar"; - post.raw = new Buffer("This is raw"); + post.raw = Buffer.from("This is raw"); post.timestamp = new Date(); post.timestampWithTimeZone = new Date(); post.timestampWithLocalTimeZone = new Date(); @@ -204,7 +204,7 @@ describe("database schema > column types > oracle", () => { post.id = 1; post.name = "Post"; post.boolean = true; - post.blob = new Buffer("This is blob"); + post.blob = Buffer.from("This is blob"); post.datetime = new Date(); await postRepository.save(post); diff --git a/test/functional/database-schema/column-types/postgres/column-types-postgres.ts b/test/functional/database-schema/column-types/postgres/column-types-postgres.ts index 9f192cc425..ba2867f4a5 100644 --- a/test/functional/database-schema/column-types/postgres/column-types-postgres.ts +++ b/test/functional/database-schema/column-types/postgres/column-types-postgres.ts @@ -48,7 +48,7 @@ describe("database schema > column types > postgres", () => { post.text = "This is text"; post.citext = "This is text"; post.hstore = "name => Alice, surname => A, age => 30"; - post.bytea = new Buffer("This is bytea"); + post.bytea = Buffer.from("This is bytea"); post.date = "2017-06-21"; post.interval = "1 year 2 months 3 days 4 hours 5 minutes 6 seconds"; post.time = "15:30:00"; diff --git a/test/functional/database-schema/column-types/sap/column-types-sap.ts b/test/functional/database-schema/column-types/sap/column-types-sap.ts index 569d5db94c..3f1f1c619d 100644 --- a/test/functional/database-schema/column-types/sap/column-types-sap.ts +++ b/test/functional/database-schema/column-types/sap/column-types-sap.ts @@ -54,12 +54,12 @@ describe("database schema > column types > sap", () => { post.timestamp.setMilliseconds(0); post.seconddate = new Date(); post.seconddate.setMilliseconds(0); - post.blob = new Buffer("This is blob"); + post.blob = Buffer.from("This is blob"); post.clob = "This is clob"; post.nclob = "This is nclob"; post.boolean = true; // post.array = ["A", "B", "C"]; // TODO - post.varbinary = new Buffer("This is varbinary"); + post.varbinary = Buffer.from("This is varbinary"); post.simpleArray = ["A", "B", "C"]; await postRepository.save(post); @@ -187,7 +187,7 @@ describe("database schema > column types > sap", () => { post.id = 1; post.name = "Post"; post.boolean = true; - post.blob = new Buffer("This is blob"); + post.blob = Buffer.from("This is blob"); post.timestamp = new Date(); await postRepository.save(post); diff --git a/test/functional/database-schema/column-types/sqlite/column-types-sqlite.ts b/test/functional/database-schema/column-types/sqlite/column-types-sqlite.ts index b44220a4b9..64a2213f22 100644 --- a/test/functional/database-schema/column-types/sqlite/column-types-sqlite.ts +++ b/test/functional/database-schema/column-types/sqlite/column-types-sqlite.ts @@ -11,7 +11,7 @@ describe("database schema > column types > sqlite", () => { before(async () => { connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"], + enabledDrivers: ["sqlite", "better-sqlite3"], }); }); beforeEach(() => reloadTestingDatabases(connections)); @@ -42,7 +42,7 @@ describe("database schema > column types > sqlite", () => { post.nchar = "This is nchar"; post.nativeCharacter = "This is native character"; post.nvarchar = "This is nvarchar"; - post.blob = new Buffer("This is blob"); + post.blob = Buffer.from("This is blob"); post.clob = "This is clob"; post.text = "This is text"; post.real = 10.5; @@ -150,7 +150,7 @@ describe("database schema > column types > sqlite", () => { post.id = 1; post.name = "Post"; post.boolean = true; - post.blob = new Buffer("A"); + post.blob = Buffer.from("A"); post.datetime = new Date(); post.datetime.setMilliseconds(0); await postRepository.save(post); diff --git a/test/functional/database-schema/simple-enums/enums.ts b/test/functional/database-schema/simple-enums/enums.ts index 61f8489342..dc35571042 100644 --- a/test/functional/database-schema/simple-enums/enums.ts +++ b/test/functional/database-schema/simple-enums/enums.ts @@ -9,7 +9,7 @@ describe("database schema > simple-enums", () => { before(async () => { connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mysql", "mariadb", "postgres", "sqlite", "mssql"] + enabledDrivers: ["mysql", "mariadb", "postgres", "sqlite", "better-sqlite3", "mssql"] }); }); beforeEach(() => reloadTestingDatabases(connections)); diff --git a/test/functional/driver/convert-to-entity/entity/Post.ts b/test/functional/driver/convert-to-entity/entity/Post.ts index aac8765a1c..e98fb2e70d 100644 --- a/test/functional/driver/convert-to-entity/entity/Post.ts +++ b/test/functional/driver/convert-to-entity/entity/Post.ts @@ -1,6 +1,6 @@ -import {Entity} from "../../../../../src"; -import {Column} from "../../../../../src"; -import {PrimaryColumn} from "../../../../../src"; +import {Entity} from "../../../../../src/decorator/entity/Entity"; +import {Column} from "../../../../../src/decorator/columns/Column"; +import {PrimaryColumn} from "../../../../../src/decorator/columns/PrimaryColumn"; @Entity() export class Post { diff --git a/test/functional/entity-metadata-validator/basic/entity-metadata-validator.ts b/test/functional/entity-metadata-validator/basic/entity-metadata-validator.ts index 76bc3c3e08..033dee81bd 100644 --- a/test/functional/entity-metadata-validator/basic/entity-metadata-validator.ts +++ b/test/functional/entity-metadata-validator/basic/entity-metadata-validator.ts @@ -1,6 +1,6 @@ -import { expect } from "chai"; import "reflect-metadata"; -import { Connection } from "../../../../src/connection/Connection"; +import {Connection} from "../../../../src/connection/Connection"; +import {expect} from "chai"; describe("entity-metadata-validator", () => { diff --git a/test/functional/entity-model/entity-model.ts b/test/functional/entity-model/entity-model.ts index 5be6481c12..baf250b473 100644 --- a/test/functional/entity-model/entity-model.ts +++ b/test/functional/entity-model/entity-model.ts @@ -3,7 +3,6 @@ import {Post} from "./entity/Post"; import {Category} from "./entity/Category"; import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; import {Connection} from "../../../src/connection/Connection"; -import {PromiseUtils} from "../../../src/util/PromiseUtils"; describe("entity-model", () => { @@ -14,60 +13,65 @@ describe("entity-model", () => { beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); - it("should save successfully and use static methods successfully", () => PromiseUtils.runInSequence(connections, async connection => { - Post.useConnection(connection); // change connection each time because of AR specifics - - const post = Post.create(); - post.title = "About ActiveRecord"; - post.text = "Huge discussion how good or bad ActiveRecord is."; - await post.save(); - - const loadedPost = await Post.findOne(post.id); - - loadedPost!.should.be.instanceOf(Post); - loadedPost!.id.should.be.eql(post.id); - loadedPost!.title.should.be.eql("About ActiveRecord"); - loadedPost!.text.should.be.eql("Huge discussion how good or bad ActiveRecord is."); - })); - - it("should reload given entity successfully", () => PromiseUtils.runInSequence(connections, async connection => { - await connection.synchronize(true); - Post.useConnection(connection); - Category.useConnection(connection); - - const category = Category.create(); - category.id = 1; - category.name = "Persistence"; - await category.save(); - - const post = Post.create(); - post.title = "About ActiveRecord"; - post.categories = [category]; - await post.save(); - - await post.reload(); - - const assertCategory = Object.assign({}, post.categories[0]); - post!.should.be.instanceOf(Post); - post!.id.should.be.eql(post.id); - post!.title.should.be.eql("About ActiveRecord"); - post!.text.should.be.eql("This is default text."); - assertCategory.should.be.eql({ - id: 1, - name: "Persistence" - }); - - category.name = "Persistence and Entity"; - await category.save(); - - await post.reload(); - - const assertReloadedCategory = Object.assign({}, post.categories[0]); - assertReloadedCategory.should.be.eql({ - id: 1, - name: "Persistence and Entity" - }); - - })); + it("should save successfully and use static methods successfully", async () => { + // These must run sequentially as we have the global context of the `Post` ActiveRecord class + for (const connection of connections) { + Post.useConnection(connection); // change connection each time because of AR specifics + + const post = Post.create(); + post.title = "About ActiveRecord"; + post.text = "Huge discussion how good or bad ActiveRecord is."; + await post.save(); + + const loadedPost = await Post.findOne(post.id); + + loadedPost!.should.be.instanceOf(Post); + loadedPost!.id.should.be.eql(post.id); + loadedPost!.title.should.be.eql("About ActiveRecord"); + loadedPost!.text.should.be.eql("Huge discussion how good or bad ActiveRecord is."); + } + }); + + it("should reload given entity successfully", async () => { + // These must run sequentially as we have the global context of the `Post` ActiveRecord class + for (const connection of connections) { + await connection.synchronize(true); + Post.useConnection(connection); + Category.useConnection(connection); + + const category = Category.create(); + category.id = 1; + category.name = "Persistence"; + await category.save(); + + const post = Post.create(); + post.title = "About ActiveRecord"; + post.categories = [category]; + await post.save(); + + await post.reload(); + + const assertCategory = Object.assign({}, post.categories[0]); + post!.should.be.instanceOf(Post); + post!.id.should.be.eql(post.id); + post!.title.should.be.eql("About ActiveRecord"); + post!.text.should.be.eql("This is default text."); + assertCategory.should.be.eql({ + id: 1, + name: "Persistence" + }); + + category.name = "Persistence and Entity"; + await category.save(); + + await post.reload(); + + const assertReloadedCategory = Object.assign({}, post.categories[0]); + assertReloadedCategory.should.be.eql({ + id: 1, + name: "Persistence and Entity" + }); + } + }); }); diff --git a/test/functional/indices/conditional-index/conditional-index.ts b/test/functional/indices/conditional-index/conditional-index.ts index 67f6648c8c..f195fe9b79 100644 --- a/test/functional/indices/conditional-index/conditional-index.ts +++ b/test/functional/indices/conditional-index/conditional-index.ts @@ -9,7 +9,7 @@ describe("indices > conditional index", () => { before(async () => { connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mssql", "postgres", "sqlite"], // only these drivers supports conditional indices + enabledDrivers: ["mssql", "postgres", "sqlite", "better-sqlite3"], // only these drivers supports conditional indices schemaCreate: true, dropSchema: true, }); @@ -37,7 +37,7 @@ describe("indices > conditional index", () => { expect(table!.indices[0].where).to.be.not.empty; expect(table!.indices[1].where).to.be.not.empty; - await queryRunner.dropIndices(table!, table!.indices); + await queryRunner.dropIndices(table!, [...table!.indices]); table = await queryRunner.getTable("post"); table!.indices.length.should.be.equal(0); diff --git a/test/functional/ltree/postgres/entity/Post.ts b/test/functional/ltree/postgres/entity/Post.ts new file mode 100644 index 0000000000..8abbf39803 --- /dev/null +++ b/test/functional/ltree/postgres/entity/Post.ts @@ -0,0 +1,14 @@ +import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn"; +import {Entity} from "../../../../../src/decorator/entity/Entity"; +import {Column} from "../../../../../src/decorator/columns/Column"; + +@Entity() +export class Post { + @PrimaryGeneratedColumn() + id: number; + + @Column("ltree", { + nullable: false + }) + path: string; +} diff --git a/test/functional/ltree/postgres/ltree-postgres.ts b/test/functional/ltree/postgres/ltree-postgres.ts new file mode 100644 index 0000000000..7e19718d84 --- /dev/null +++ b/test/functional/ltree/postgres/ltree-postgres.ts @@ -0,0 +1,136 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import { Connection } from "../../../../src/connection/Connection"; +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases +} from "../../../utils/test-utils"; +import { Post } from "./entity/Post"; + +describe("ltree-postgres", () => { + let connections: Connection[]; + before(async () => { + connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + enabledDrivers: ["postgres"] + }); + }); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should create correct schema with Postgres' ltree type", () => + Promise.all( + connections.map(async connection => { + const queryRunner = connection.createQueryRunner(); + const schema = await queryRunner.getTable("post"); + await queryRunner.release(); + expect(schema).not.to.be.undefined; + const ltreeColumn = schema!.columns.find( + tableColumn => + tableColumn.name === "path" && + tableColumn.type === "ltree" && + !tableColumn.isArray + ); + expect(ltreeColumn).to.not.be.undefined; + }) + )); + + it("should persist ltree correctly", () => + Promise.all( + connections.map(async connection => { + const path = 'News.Featured.Opinion'; + const postRepo = connection.getRepository(Post); + const post = new Post(); + post.path = path; + const persistedPost = await postRepo.save(post); + const foundPost = await postRepo.findOne(persistedPost.id); + expect(foundPost).to.exist; + expect(foundPost!.path).to.deep.equal(path); + }) + )); + + it("should update ltree correctly", () => + Promise.all( + connections.map(async connection => { + const path = 'News.Featured.Opinion'; + const path2 = 'News.Featured.Gossip'; + const postRepo = connection.getRepository(Post); + const post = new Post(); + post.path = path; + const persistedPost = await postRepo.save(post); + + await postRepo.update( + { id: persistedPost.id }, + { path: path2 } + ); + + const foundPost = await postRepo.findOne(persistedPost.id); + expect(foundPost).to.exist; + expect(foundPost!.path).to.deep.equal(path2); + }) + )); + + it("should re-save ltree correctly", () => + Promise.all( + connections.map(async connection => { + const path = 'News.Featured.Opinion'; + const path2 = 'News.Featured.Gossip'; + const postRepo = connection.getRepository(Post); + const post = new Post(); + post.path = path; + const persistedPost = await postRepo.save(post); + + persistedPost.path = path2; + await postRepo.save(persistedPost); + + const foundPost = await postRepo.findOne(persistedPost.id); + expect(foundPost).to.exist; + expect(foundPost!.path).to.deep.equal(path2); + }) + )); + + it("should persist ltree correctly with trailing '.'", () => + Promise.all( + connections.map(async connection => { + const path = 'News.Featured.Opinion.'; + const postRepo = connection.getRepository(Post); + const post = new Post(); + post.path = path; + const persistedPost = await postRepo.save(post); + const foundPost = await postRepo.findOne(persistedPost.id); + expect(foundPost).to.exist; + expect(foundPost!.path).to.deep.equal('News.Featured.Opinion'); + }) + )); + + it("should persist ltree correctly when containing spaces", () => + Promise.all( + connections.map(async connection => { + const path = 'News.Featured Story.Opinion'; + const postRepo = connection.getRepository(Post); + const post = new Post(); + post.path = path; + const persistedPost = await postRepo.save(post); + const foundPost = await postRepo.findOne(persistedPost.id); + expect(foundPost).to.exist; + expect(foundPost!.path).to.deep.equal('News.Featured_Story.Opinion'); + }) + )); + + it("should be able to query ltree correctly", () => + Promise.all( + connections.map(async connection => { + const path = 'News.Featured.Opinion'; + const postRepo = connection.getRepository(Post); + const post = new Post(); + post.path = path; + await postRepo.save(post); + const foundPost = await postRepo.createQueryBuilder().where(`path ~ 'news@.*'`).getOne() + expect(foundPost).to.exist; + expect(foundPost!.path).to.deep.equal(path); + }) + )); +}); + + diff --git a/test/functional/migrations/generate-command/command.ts b/test/functional/migrations/generate-command/command.ts new file mode 100644 index 0000000000..1c13633428 --- /dev/null +++ b/test/functional/migrations/generate-command/command.ts @@ -0,0 +1,36 @@ +import "reflect-metadata"; +import {createTestingConnections, closeTestingConnections, /*reloadTestingDatabases*/} from "../../../utils/test-utils"; +import {Connection} from "../../../../src/connection/Connection"; +import { Category, Post } from "./entity"; + +describe("migrations > generate command", () => { + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + migrations: [], + enabledDrivers: ["postgres"], + schemaCreate: false, + dropSchema: true, + entities: [Post, Category], + logging: true, + schema: "public", + })); + // beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("can recognize model changes", () => Promise.all(connections.map(async connection => { + const sqlInMemory = await connection.driver.createSchemaBuilder().log(); + sqlInMemory.upQueries.length.should.be.greaterThan(0); + sqlInMemory.downQueries.length.should.be.greaterThan(0); + }))); + + it("does not generate when no model changes", () => Promise.all(connections.map(async connection => { + await connection.driver.createSchemaBuilder().build(); + + const sqlInMemory = await connection.driver.createSchemaBuilder().log(); + + console.log(sqlInMemory.upQueries); + sqlInMemory.upQueries.length.should.be.equal(0); + sqlInMemory.downQueries.length.should.be.equal(0); + + }))); + }); diff --git a/test/functional/migrations/generate-command/entity/category.entity.ts b/test/functional/migrations/generate-command/entity/category.entity.ts new file mode 100644 index 0000000000..226f8f5991 --- /dev/null +++ b/test/functional/migrations/generate-command/entity/category.entity.ts @@ -0,0 +1,15 @@ +import {PrimaryColumn} from "../../../../../src/decorator/columns/PrimaryColumn"; +import {Entity} from "../../../../../src/decorator/entity/Entity"; +import {BaseEntity} from "../../../../../src/repository/BaseEntity"; +import {Column} from "../../../../../src/decorator/columns/Column"; + +@Entity("category_test", { schema: "public" }) +export class Category extends BaseEntity { + + @PrimaryColumn() + id: number; + + @Column() + name: string; + +} diff --git a/test/functional/migrations/generate-command/entity/index.ts b/test/functional/migrations/generate-command/entity/index.ts new file mode 100644 index 0000000000..1560189f7f --- /dev/null +++ b/test/functional/migrations/generate-command/entity/index.ts @@ -0,0 +1,3 @@ +export {Post} from "./post.entity"; +export {Category} from "./category.entity"; +export {Tag} from "./tag.entity"; \ No newline at end of file diff --git a/test/functional/migrations/generate-command/entity/post.entity.ts b/test/functional/migrations/generate-command/entity/post.entity.ts new file mode 100644 index 0000000000..b83c371a1d --- /dev/null +++ b/test/functional/migrations/generate-command/entity/post.entity.ts @@ -0,0 +1,26 @@ +import {Entity} from "../../../../../src/decorator/entity/Entity"; +import {BaseEntity} from "../../../../../src/repository/BaseEntity"; +import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn"; +import {Column} from "../../../../../src/decorator/columns/Column"; +import {ManyToMany, JoinTable} from "../../../../../src"; +import {Category} from "./category.entity"; + +@Entity("post_test", { schema: "public" }) +export class Post extends BaseEntity { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + title: string; + + @Column({ + default: "This is default text." + }) + text: string; + + @ManyToMany(type => Category) + @JoinTable() + categories: Category[]; + +} \ No newline at end of file diff --git a/test/functional/migrations/generate-command/entity/tag.entity.ts b/test/functional/migrations/generate-command/entity/tag.entity.ts new file mode 100644 index 0000000000..eab5ad2290 --- /dev/null +++ b/test/functional/migrations/generate-command/entity/tag.entity.ts @@ -0,0 +1,21 @@ +import {PrimaryColumn} from "../../../../../src/decorator/columns/PrimaryColumn"; +import {ManyToOne} from "../../../../../src/decorator/relations/ManyToOne"; +import {JoinColumn} from "../../../../../src/decorator/relations/JoinColumn"; +import {Entity} from "../../../../../src/decorator/entity/Entity"; +import {BaseEntity} from "../../../../../src/repository/BaseEntity"; +import {Column} from "../../../../../src/decorator/columns/Column"; +import {Post} from "./post.entity"; + +@Entity("tag_test", { schema: "public" }) +export class Tag extends BaseEntity { + + @PrimaryColumn() + id: number; + + @Column() + name: string; + + @ManyToOne(() => Post) + @JoinColumn({ name: "tag_to_post" }) + posts: Post | null; +} diff --git a/test/functional/persistence/multi-primary-key/multi-primary-key.ts b/test/functional/persistence/multi-primary-key/multi-primary-key.ts index 7e9fbc4fc0..dab63f48aa 100644 --- a/test/functional/persistence/multi-primary-key/multi-primary-key.ts +++ b/test/functional/persistence/multi-primary-key/multi-primary-key.ts @@ -1,6 +1,6 @@ import "reflect-metadata"; import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils"; -import {Connection} from "../../../../src"; +import {Connection} from "../../../../src/connection/Connection"; import {Post} from "./entity/Post"; import {Category} from "./entity/Category"; diff --git a/test/functional/persistence/persistence-order/persistence-order.ts b/test/functional/persistence/persistence-order/persistence-order.ts index ca1bb124b9..7fb537b261 100644 --- a/test/functional/persistence/persistence-order/persistence-order.ts +++ b/test/functional/persistence/persistence-order/persistence-order.ts @@ -1,9 +1,9 @@ -import { expect } from "chai"; import "reflect-metadata"; -import { Connection } from "../../../../src/connection/Connection"; -import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../../utils/test-utils"; -import { Category } from "./entity/Category"; -import { Post } from "./entity/Post"; +import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils"; +import {Connection} from "../../../../src/connection/Connection"; +import {Post} from "./entity/Post"; +import {Category} from "./entity/Category"; +import {expect} from "chai"; describe("persistence > order of persistence execution operations", () => { diff --git a/test/functional/query-builder/count/entity/Test.ts b/test/functional/query-builder/count/entity/Test.ts new file mode 100644 index 0000000000..360fce0ac0 --- /dev/null +++ b/test/functional/query-builder/count/entity/Test.ts @@ -0,0 +1,13 @@ +import {Entity, PrimaryColumn} from "../../../../../src"; + +@Entity("tests") +export class Test { + @PrimaryColumn() + varcharField: string; + + @PrimaryColumn("uuid") + uuidField: string; + + @PrimaryColumn() + intField: number; +} diff --git a/test/functional/query-builder/count/query-builder-count.ts b/test/functional/query-builder/count/query-builder-count.ts new file mode 100644 index 0000000000..39990f9d38 --- /dev/null +++ b/test/functional/query-builder/count/query-builder-count.ts @@ -0,0 +1,22 @@ +import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils"; +import {Connection} from "../../../../src/connection/Connection"; +import {expect} from "chai"; +import {Test} from "./entity/Test"; + +describe("query builder > count", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [Test], + schemaCreate: true, + dropSchema: true, + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("Count query should be completed successfully", () => Promise.all(connections.map(async connection => { + const count = await connection.getRepository(Test).count(); + expect(count).to.be.equal(0); + }))); + +}); diff --git a/test/functional/query-builder/delete/query-builder-delete.ts b/test/functional/query-builder/delete/query-builder-delete.ts index 6bc071130c..4c7be03883 100644 --- a/test/functional/query-builder/delete/query-builder-delete.ts +++ b/test/functional/query-builder/delete/query-builder-delete.ts @@ -4,6 +4,7 @@ import {closeTestingConnections, createTestingConnections, reloadTestingDatabase import {Connection} from "../../../../src/connection/Connection"; import {User} from "./entity/User"; import {Photo} from "./entity/Photo"; +import {EntityColumnNotFound} from "../../../../src/error/EntityColumnNotFound"; describe("query builder > delete", () => { @@ -95,6 +96,7 @@ describe("query builder > delete", () => { it("should return correct delete result", () => Promise.all(connections.map(async connection => { // don't run test for sqlite and sqljs as they don't return affected rows + // better-sqlite3 works correctly if (connection.name === "sqlite" || connection.name === "sqljs" || connection.name === "sap") return; @@ -113,4 +115,24 @@ describe("query builder > delete", () => { expect(result.affected).to.equal(2); }))); + it("should throw error when unknown property in where criteria", () => Promise.all(connections.map(async connection => { + + const user = new User(); + user.name = "Alex Messer"; + + await connection.manager.save(user); + + let error: Error | undefined; + try { + await connection.createQueryBuilder() + .delete() + .from(User) + .where( { unknownProp: "Alex Messer" }) + .execute(); + } catch (err) { + error = err; + } + expect(error).to.be.an.instanceof(EntityColumnNotFound); + + }))); }); diff --git a/test/functional/query-builder/insert-on-conflict/query-builder-insert-on-conflict.ts b/test/functional/query-builder/insert-on-conflict/query-builder-insert-on-conflict.ts index 03ee8e50bd..67221d0f30 100644 --- a/test/functional/query-builder/insert-on-conflict/query-builder-insert-on-conflict.ts +++ b/test/functional/query-builder/insert-on-conflict/query-builder-insert-on-conflict.ts @@ -8,7 +8,7 @@ describe("query builder > insertion > on conflict", () => { let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["postgres", "sqlite"] // since on conflict statement is only supported in postgres and sqlite >= 3.24.0 + enabledDrivers: ["postgres", "sqlite", "better-sqlite3"] // since on conflict statement is only supported in postgres and sqlite >= 3.24.0 })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/functional/query-builder/join/query-builder-joins.ts b/test/functional/query-builder/join/query-builder-joins.ts index 56cb0f8c07..91060ce870 100644 --- a/test/functional/query-builder/join/query-builder-joins.ts +++ b/test/functional/query-builder/join/query-builder-joins.ts @@ -1,7 +1,7 @@ import "reflect-metadata"; import {expect} from "chai"; import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils"; -import {Connection} from "../../../../src"; +import {Connection} from "../../../../src/connection/Connection"; import {Tag} from "./entity/Tag"; import {Post} from "./entity/Post"; import {Category} from "./entity/Category"; diff --git a/test/functional/query-builder/locking/query-builder-locking.ts b/test/functional/query-builder/locking/query-builder-locking.ts index eefdddfd05..adcf742087 100644 --- a/test/functional/query-builder/locking/query-builder-locking.ts +++ b/test/functional/query-builder/locking/query-builder-locking.ts @@ -77,6 +77,28 @@ describe("query builder > locking", () => { }); }))); + it("should throw error if for no key update lock used without transaction", () => Promise.all(connections.map(async connection => { + if (connection.driver instanceof PostgresDriver) { + return connection.createQueryBuilder(PostWithVersion, "post") + .setLock("for_no_key_update") + .where("post.id = :id", { id: 1 }) + .getOne().should.be.rejectedWith(PessimisticLockTransactionRequiredError); + } + return; + }))); + + it("should not throw error if for no key update lock used with transaction", () => Promise.all(connections.map(async connection => { + if (connection.driver instanceof PostgresDriver) { + return connection.manager.transaction(entityManager => { + return Promise.all([entityManager.createQueryBuilder(PostWithVersion, "post") + .setLock("for_no_key_update") + .where("post.id = :id", { id: 1}) + .getOne().should.not.be.rejected]); + }); + } + return; + }))); + it("should attach pessimistic read lock statement on query if locking enabled", () => Promise.all(connections.map(async connection => { if (connection.driver instanceof AbstractSqliteDriver || connection.driver instanceof CockroachDriver || connection.driver instanceof SapDriver) return; @@ -141,6 +163,30 @@ describe("query builder > locking", () => { }))); + it("should not attach for no key update lock statement on query if locking is not used", () => Promise.all(connections.map(async connection => { + if (connection.driver instanceof PostgresDriver) { + const sql = connection.createQueryBuilder(PostWithVersion, "post") + .where("post.id = :id", { id: 1 }) + .getSql(); + + expect(sql.indexOf("FOR NO KEY UPDATE") === -1).to.be.true; + } + return; + }))); + + it("should attach for no key update lock statement on query if locking enabled", () => Promise.all(connections.map(async connection => { + if (connection.driver instanceof PostgresDriver) { + const sql = connection.createQueryBuilder(PostWithVersion, "post") + .setLock("for_no_key_update") + .where("post.id = :id", { id: 1 }) + .getSql(); + + expect(sql.indexOf("FOR NO KEY UPDATE") !== -1).to.be.true; + } + return; + + }))); + it("should throw error if optimistic lock used with getMany method", () => Promise.all(connections.map(async connection => { return connection.createQueryBuilder(PostWithVersion, "post") @@ -291,4 +337,19 @@ describe("query builder > locking", () => { return; }))); + it("should throw error if for no key update locking not supported by given driver", () => Promise.all(connections.map(async connection => { + if (!(connection.driver instanceof PostgresDriver)) { + return connection.manager.transaction(entityManager => { + return Promise.all([ + entityManager.createQueryBuilder(PostWithVersion, "post") + .setLock("for_no_key_update") + .where("post.id = :id", { id: 1 }) + .getOne().should.be.rejectedWith(LockNotSupportedOnGivenDriverError), + ]); + }); + } + + return; + }))); + }); diff --git a/test/functional/query-builder/order-by/query-builder-order-by.ts b/test/functional/query-builder/order-by/query-builder-order-by.ts index 8ff9242396..4db3c69a99 100644 --- a/test/functional/query-builder/order-by/query-builder-order-by.ts +++ b/test/functional/query-builder/order-by/query-builder-order-by.ts @@ -135,4 +135,4 @@ describe("query builder > order-by", () => { expect(loadedPost2!.num2).to.be.equal(2); }))); -}); \ No newline at end of file +}); diff --git a/test/functional/query-builder/subquery/query-builder-subquery.ts b/test/functional/query-builder/subquery/query-builder-subquery.ts index 0e319b16dd..437f259967 100644 --- a/test/functional/query-builder/subquery/query-builder-subquery.ts +++ b/test/functional/query-builder/subquery/query-builder-subquery.ts @@ -1,6 +1,6 @@ import "reflect-metadata"; import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils"; -import {Connection} from "../../../../src"; +import {Connection} from "../../../../src/connection/Connection"; import {User} from "./entity/User"; import {Post} from "./entity/Post"; import {Category} from "./entity/Category"; diff --git a/test/functional/query-builder/update/query-builder-update.ts b/test/functional/query-builder/update/query-builder-update.ts index 17c55ee509..da4c33dabc 100644 --- a/test/functional/query-builder/update/query-builder-update.ts +++ b/test/functional/query-builder/update/query-builder-update.ts @@ -249,4 +249,25 @@ describe("query builder > update", () => { }))); + it("should throw error when unknown property in where criteria", () => Promise.all(connections.map(async connection => { + + const user = new User(); + user.name = "Alex Messer"; + + await connection.manager.save(user); + + let error: Error | undefined; + try { + await connection.createQueryBuilder() + .update(User) + .set({ name: "John Doe" } as any) + .where( { unknownProp: "Alex Messer" }) + .execute(); + } catch (err) { + error = err; + } + expect(error).to.be.an.instanceof(EntityColumnNotFound); + + }))); + }); diff --git a/test/functional/query-runner/create-table.ts b/test/functional/query-runner/create-table.ts index f940faf7ea..3aa973fcea 100644 --- a/test/functional/query-runner/create-table.ts +++ b/test/functional/query-runner/create-table.ts @@ -12,7 +12,6 @@ import {AbstractSqliteDriver} from "../../../src/driver/sqlite-abstract/Abstract import {OracleDriver} from "../../../src/driver/oracle/OracleDriver"; import {Photo} from "./entity/Photo"; import {Book2, Book} from "./entity/Book"; -import {SqliteDriver} from "../../../src/driver/sqlite/SqliteDriver"; describe("query runner > create table", () => { @@ -332,7 +331,7 @@ describe("query runner > create table", () => { it("should correctly create table with different `withoutRowid` definitions", () => Promise.all(connections.map(async connection => { - if (connection.driver instanceof SqliteDriver) { + if (connection.driver instanceof AbstractSqliteDriver) { const queryRunner = connection.createQueryRunner(); // the table 'book' must contain a 'rowid' column @@ -358,7 +357,7 @@ describe("query runner > create table", () => { try { await connection.manager.query("SELECT rowid FROM book2"); } catch (e) { - expect(e.message).equal("SQLITE_ERROR: no such column: rowid"); + expect(e.message).contains("no such column: rowid"); } await queryRunner.dropTable("book2"); diff --git a/test/functional/query-runner/create-unique-constraint.ts b/test/functional/query-runner/create-unique-constraint.ts index ba39b2aa98..b3022e0a36 100644 --- a/test/functional/query-runner/create-unique-constraint.ts +++ b/test/functional/query-runner/create-unique-constraint.ts @@ -10,7 +10,7 @@ describe("query runner > create unique constraint", () => { before(async () => { connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mssql", "postgres", "sqlite", "oracle", "cockroachdb"], // mysql and sap does not supports unique constraints + enabledDrivers: ["mssql", "postgres", "sqlite", "better-sqlite3", "oracle", "cockroachdb"], // mysql and sap does not supports unique constraints schemaCreate: true, dropSchema: true, }); diff --git a/test/functional/query-runner/drop-column.ts b/test/functional/query-runner/drop-column.ts index 5e03628eee..2c422c2e9d 100644 --- a/test/functional/query-runner/drop-column.ts +++ b/test/functional/query-runner/drop-column.ts @@ -28,6 +28,11 @@ describe("query runner > drop column", () => { nameColumn!.should.be.exist; versionColumn!.should.be.exist; + // better-sqlite3 seems not able to create a check constraint on a non-existing column + if (connection.name === "better-sqlite3") { + await queryRunner.dropCheckConstraints(table!, table!.checks); + } + // In Sqlite 'dropColumns' method is more optimal than 'dropColumn', because it recreate table just once, // without all removed columns. In other drivers it's no difference between these methods, because 'dropColumns' // calls 'dropColumn' method for each removed column. diff --git a/test/functional/query-runner/drop-unique-constraint.ts b/test/functional/query-runner/drop-unique-constraint.ts index fd00a7952d..d2b5d5bcb0 100644 --- a/test/functional/query-runner/drop-unique-constraint.ts +++ b/test/functional/query-runner/drop-unique-constraint.ts @@ -8,7 +8,7 @@ describe("query runner > drop unique constraint", () => { before(async () => { connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mssql", "postgres", "sqlite", "oracle", "cockroachdb"], // mysql and sap does not supports unique constraints + enabledDrivers: ["mssql", "postgres", "sqlite", "better-sqlite3", "oracle", "cockroachdb"], // mysql and sap does not supports unique constraints schemaCreate: true, dropSchema: true, }); diff --git a/test/functional/query-runner/has-column.ts b/test/functional/query-runner/has-column.ts new file mode 100644 index 0000000000..75903b8b73 --- /dev/null +++ b/test/functional/query-runner/has-column.ts @@ -0,0 +1,33 @@ +import "reflect-metadata"; +import {Connection} from "../../../src/connection/Connection"; +import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils"; + +describe("query runner > has column", () => { + + let connections: Connection[]; + before(async () => { + connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + schemaCreate: true, + dropSchema: true, + }); + }); + after(() => closeTestingConnections(connections)); + + it("should correctly check if column exist", () => Promise.all(connections.map(async connection => { + const queryRunner = connection.createQueryRunner(); + + let hasIdColumn = await queryRunner.hasColumn("post", "id"); + let hasNameColumn = await queryRunner.hasColumn("post", "name"); + let hasVersionColumn = await queryRunner.hasColumn("post", "version"); + let hasDescriptionColumn = await queryRunner.hasColumn("post", "description"); + + hasIdColumn.should.be.true; + hasNameColumn.should.be.true; + hasVersionColumn.should.be.true; + hasDescriptionColumn.should.be.false; + + await queryRunner.release(); + }))); + +}); diff --git a/test/functional/relations/eager-relations/circular-eager-relations/circular-eager-relations.ts b/test/functional/relations/eager-relations/circular-eager-relations/circular-eager-relations.ts index f3a5eee0b7..faa9d4bd0a 100644 --- a/test/functional/relations/eager-relations/circular-eager-relations/circular-eager-relations.ts +++ b/test/functional/relations/eager-relations/circular-eager-relations/circular-eager-relations.ts @@ -1,6 +1,6 @@ -import { expect } from "chai"; import "reflect-metadata"; -import { Connection } from "../../../../../src/connection/Connection"; +import {Connection} from "../../../../../src/connection/Connection"; +import {expect} from "chai"; describe("relations > eager relations > circular eager relations", () => { diff --git a/test/functional/relations/lazy-relations/basic-lazy-relation/basic-lazy-relations.ts b/test/functional/relations/lazy-relations/basic-lazy-relation/basic-lazy-relations.ts index 3c0d8fe7d1..7c83e84e39 100644 --- a/test/functional/relations/lazy-relations/basic-lazy-relation/basic-lazy-relations.ts +++ b/test/functional/relations/lazy-relations/basic-lazy-relation/basic-lazy-relations.ts @@ -326,7 +326,7 @@ describe("basic-lazy-relations", () => { loadedPost.title.should.be.equal("post with great category"); }))); - it("should successfully load relations within a transaction", () => Promise.all(connections.filter((connection) => (new Set(["mysql", "sqlite", "postgres"])).has(connection.options.type)).map(async connection => { + it("should successfully load relations within a transaction", () => Promise.all(connections.filter((connection) => (new Set(["mysql", "sqlite", "better-sqlite3", "postgres"])).has(connection.options.type)).map(async connection => { await connection.manager.transaction(async (manager) => { const category = new Category(); category.name = "category of great post"; @@ -344,7 +344,7 @@ describe("basic-lazy-relations", () => { }); }))); - it("should successfully load relations outside a transaction with entity generated within a transaction", () => Promise.all(connections.filter((connection) => (new Set(["mysql", "sqlite", "postgres"])).has(connection.options.type)).map(async connection => { + it("should successfully load relations outside a transaction with entity generated within a transaction", () => Promise.all(connections.filter((connection) => (new Set(["mysql", "sqlite", "better-sqlite3", "postgres"])).has(connection.options.type)).map(async connection => { const loadedCategory = await connection.manager.transaction(async (manager) => { const category = new Category(); category.name = "category of great post"; diff --git a/test/functional/repository/basic-methods/repository-basic-methods.ts b/test/functional/repository/basic-methods/repository-basic-methods.ts index 2d36063c1e..d7a31244dc 100644 --- a/test/functional/repository/basic-methods/repository-basic-methods.ts +++ b/test/functional/repository/basic-methods/repository-basic-methods.ts @@ -326,8 +326,7 @@ describe("repository > basic methods", () => { }); describe("save", function () { - it("should update existing entity using transformers", async () => { - const connection = connections.find((c: Connection) => c.name === "sqlite"); + it("should update existing entity using transformers", () => Promise.all(connections.filter(c => c.name === "sqlite" || c.name === "better-sqlite3").map(async connection => { if (!connection || (connection.options as any).skip === true) { return; } @@ -356,7 +355,7 @@ describe("repository > basic methods", () => { saved.title.should.be.equal("New title"); saved.dateAdded.should.be.instanceof(Date); saved.dateAdded.getTime().should.be.equal(date.getTime()); - }); + }))); }); describe("preload also should also implement merge functionality", function() { diff --git a/test/functional/repository/find-options-operators/repository-find-operators.ts b/test/functional/repository/find-options-operators/repository-find-operators.ts index c437be4a6f..84a7ab8828 100644 --- a/test/functional/repository/find-options-operators/repository-find-operators.ts +++ b/test/functional/repository/find-options-operators/repository-find-operators.ts @@ -5,6 +5,7 @@ import { Between, Connection, Equal, + Switch, If, ILike, In, @@ -14,13 +15,11 @@ import { Like, MoreThan, MoreThanOrEqual, - Not, - PromiseUtils, - Raw, - Switch + Not } from "../../../../src"; import {Post} from "./entity/Post"; import {PostgresDriver} from "../../../../src/driver/postgres/PostgresDriver"; +import {Raw} from "../../../../src/find-options/operator/Raw"; import {PersonAR} from "./entity/PersonAR"; import {expect} from "chai"; @@ -544,7 +543,7 @@ describe("repository > find options > operators", () => { it("not(ilike)", () => Promise.all(connections.map(async connection => { if (!(connection.driver instanceof PostgresDriver)) return; - + // insert some fake data const post1 = new Post(); post1.title = "about #1"; @@ -1157,18 +1156,20 @@ describe("repository > find options > operators", () => { }))); - it("should work with ActiveRecord model", () => PromiseUtils.runInSequence(connections, async connection => { - PersonAR.useConnection(connection); - - const person = new PersonAR(); - person.name = "Timber"; - await connection.manager.save(person); - - const loadedPeople = await PersonAR.find({ - name: In(["Timber"]) - }); - expect(loadedPeople[0].name).to.be.equal("Timber"); - - })); + it("should work with ActiveRecord model", async () => { + // These must run sequentially as we have the global context of the `PersonAR` ActiveRecord class + for (const connection of connections) { + PersonAR.useConnection(connection); + + const person = new PersonAR(); + person.name = "Timber"; + await connection.manager.save(person); + + const loadedPeople = await PersonAR.find({ + name: In(["Timber"]) + }); + expect(loadedPeople[0].name).to.be.equal("Timber"); + } + }); }); diff --git a/test/functional/repository/find-options/repository-find-options.ts b/test/functional/repository/find-options/repository-find-options.ts index 42bffc16e1..e899d6158c 100644 --- a/test/functional/repository/find-options/repository-find-options.ts +++ b/test/functional/repository/find-options/repository-find-options.ts @@ -12,7 +12,7 @@ describe("repository > find options", () => { let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"] + enabledDrivers: ["sqlite", "better-sqlite3"] })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/functional/repository/soft-delete/entity-soft-remove.ts b/test/functional/repository/soft-delete/entity-soft-remove.ts new file mode 100644 index 0000000000..06cb188756 --- /dev/null +++ b/test/functional/repository/soft-delete/entity-soft-remove.ts @@ -0,0 +1,101 @@ +import "reflect-metadata"; +import {expect} from "chai"; +import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils"; +import {Connection} from "../../../../src/connection/Connection"; +import {Post} from "./entity/Post"; +import { PostWithoutDeleteDateColumn } from "./entity/PostWithoutDeleteDateColumn"; +import { MissingDeleteDateColumnError } from "../../../../src/error/MissingDeleteDateColumnError"; + +describe("entity > soft-remove", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should perform soft removal and recovery correctly", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(Post); + + // save a new posts + const newPost1 = postRepository.create({ + id: 1, + name: "post#1" + }); + const newPost2 = postRepository.create({ + id: 2, + name: "post#2" + }); + + await postRepository.save(newPost1); + await postRepository.save(newPost2); + + // soft-remove one + await postRepository.softRemove(newPost1); + + // load to check + const loadedPosts = await postRepository.find({ options: { withDeleted: true } }); + + // assert + loadedPosts.length.should.be.equal(2); + + const loadedPost1 = loadedPosts.find(p => p.id === 1); + expect(loadedPost1).to.exist; + expect(loadedPost1!.deletedAt).to.be.instanceof(Date); + expect(loadedPost1!.name).to.equals("post#1"); + const loadedPost2 = loadedPosts.find(p => p.id === 2); + expect(loadedPost2).to.exist; + expect(loadedPost2!.deletedAt).to.equals(null); + expect(loadedPost2!.name).to.equals("post#2"); + + // recover one + await postRepository.recover(loadedPost1!); + + // load to check + const recoveredPosts = await postRepository.find({ options: { withDeleted: true } }); + + // assert + recoveredPosts.length.should.be.equal(2); + + const recoveredPost1 = recoveredPosts.find(p => p.id === 1); + expect(recoveredPost1).to.exist; + expect(recoveredPost1!.deletedAt).to.equals(null); + expect(recoveredPost1!.name).to.equals("post#1"); + const recoveredPost2 = recoveredPosts.find(p => p.id === 2); + expect(recoveredPost2).to.exist; + expect(recoveredPost2!.deletedAt).to.equals(null); + expect(recoveredPost2!.name).to.equals("post#2"); + }))); + + it("should throw error when delete date column is missing", () => Promise.all(connections.map(async connection => { + const postRepository = connection.getRepository(PostWithoutDeleteDateColumn); + + // save a new posts + const newPost1 = postRepository.create({ + id: 1, + name: "post#1" + }); + + await postRepository.save(newPost1); + + let error1: Error | undefined; + try { + // soft-remove one + await postRepository.softRemove(newPost1); + } catch (err) { + error1 = err; + } + expect(error1).to.be.an.instanceof(MissingDeleteDateColumnError); + + let error2: Error | undefined; + try { + // recover one + await postRepository.recover(newPost1); + } catch (err) { + error2 = err; + } + expect(error2).to.be.an.instanceof(MissingDeleteDateColumnError); + + }))); +}); diff --git a/test/functional/repository/soft-delete/entity/Post.ts b/test/functional/repository/soft-delete/entity/Post.ts index 8931d66597..cc4dbea778 100644 --- a/test/functional/repository/soft-delete/entity/Post.ts +++ b/test/functional/repository/soft-delete/entity/Post.ts @@ -2,9 +2,10 @@ import {Entity} from "../../../../../src/decorator/entity/Entity"; import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn"; import {Column} from "../../../../../src/decorator/columns/Column"; import {DeleteDateColumn} from "../../../../../src/decorator/columns/DeleteDateColumn"; +import {BaseEntity} from "../../../../../src"; @Entity() -export class Post { +export class Post extends BaseEntity { @PrimaryGeneratedColumn() id: number; @@ -13,4 +14,4 @@ export class Post { @Column() name: string; -} \ No newline at end of file +} diff --git a/test/functional/repository/soft-delete/entity/PostWithoutDeleteDateColumn.ts b/test/functional/repository/soft-delete/entity/PostWithoutDeleteDateColumn.ts index 2001119958..96235d75ff 100644 --- a/test/functional/repository/soft-delete/entity/PostWithoutDeleteDateColumn.ts +++ b/test/functional/repository/soft-delete/entity/PostWithoutDeleteDateColumn.ts @@ -1,12 +1,13 @@ import {Entity} from "../../../../../src/decorator/entity/Entity"; import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn"; import {Column} from "../../../../../src/decorator/columns/Column"; +import {BaseEntity} from "../../../../../src"; @Entity() -export class PostWithoutDeleteDateColumn { +export class PostWithoutDeleteDateColumn extends BaseEntity { @PrimaryGeneratedColumn() id: number; @Column() name: string; -} \ No newline at end of file +} diff --git a/test/functional/schema-builder/change-check-constraint.ts b/test/functional/schema-builder/change-check-constraint.ts index 5996b4eaf3..5e6d6cbf1a 100644 --- a/test/functional/schema-builder/change-check-constraint.ts +++ b/test/functional/schema-builder/change-check-constraint.ts @@ -1,7 +1,6 @@ import "reflect-metadata"; import {Connection} from "../../../src/connection/Connection"; import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; -import {PromiseUtils} from "../../../src"; import {Teacher} from "./entity/Teacher"; import {Post} from "./entity/Post"; import {CheckMetadata} from "../../../src/metadata/CheckMetadata"; @@ -20,7 +19,7 @@ describe("schema builder > change check constraint", () => { beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); - it("should correctly add new check constraint", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly add new check constraint", () => Promise.all(connections.map(async connection => { // Mysql does not support check constraints. if (connection.driver instanceof MysqlDriver) return; @@ -43,9 +42,9 @@ describe("schema builder > change check constraint", () => { await queryRunner.release(); table!.checks.length.should.be.equal(1); - })); + }))); - it("should correctly change check", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly change check", () => Promise.all(connections.map(async connection => { // Mysql does not support check constraints. if (connection.driver instanceof MysqlDriver) return; @@ -61,9 +60,9 @@ describe("schema builder > change check constraint", () => { await queryRunner.release(); table!.checks[0].expression!.indexOf("2000").should.be.not.equal(-1); - })); + }))); - it("should correctly drop removed check", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly drop removed check", () => Promise.all(connections.map(async connection => { // Mysql does not support check constraints. if (connection.driver instanceof MysqlDriver) return; @@ -78,6 +77,6 @@ describe("schema builder > change check constraint", () => { await queryRunner.release(); table!.checks.length.should.be.equal(0); - })); + }))); }); diff --git a/test/functional/schema-builder/change-column.ts b/test/functional/schema-builder/change-column.ts index 2372e47400..2b21f5f02b 100644 --- a/test/functional/schema-builder/change-column.ts +++ b/test/functional/schema-builder/change-column.ts @@ -1,6 +1,6 @@ import {expect} from "chai"; import "reflect-metadata"; -import {Connection, PromiseUtils} from "../../../src"; +import {Connection} from "../../../src"; import {AuroraDataApiDriver} from "../../../src/driver/aurora-data-api/AuroraDataApiDriver"; import {CockroachDriver} from "../../../src/driver/cockroachdb/CockroachDriver"; import {MysqlDriver} from "../../../src/driver/mysql/MysqlDriver"; @@ -26,7 +26,7 @@ describe("schema builder > change column", () => { beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); - it("should correctly change column name", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly change column name", () => Promise.all(connections.map(async connection => { const postMetadata = connection.getMetadata(Post); const nameColumn = postMetadata.findColumnWithPropertyName("name")!; nameColumn.propertyName = "title"; @@ -44,9 +44,9 @@ describe("schema builder > change column", () => { // revert changes nameColumn.propertyName = "name"; nameColumn.build(connection); - })); + }))); - it("should correctly change column length", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly change column length", () => Promise.all(connections.map(async connection => { const postMetadata = connection.getMetadata(Post); const nameColumn = postMetadata.findColumnWithPropertyName("name")!; const textColumn = postMetadata.findColumnWithPropertyName("text")!; @@ -71,9 +71,9 @@ describe("schema builder > change column", () => { // revert changes nameColumn.length = "255"; textColumn.length = "255"; - })); + }))); - it("should correctly change column type", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly change column type", () => Promise.all(connections.map(async connection => { const postMetadata = connection.getMetadata(Post); const versionColumn = postMetadata.findColumnWithPropertyName("version")!; @@ -95,9 +95,9 @@ describe("schema builder > change column", () => { // revert changes versionColumn.type = "varchar"; postVersionColumn.type = "varchar"; - })); + }))); - it("should correctly make column primary and generated", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly make column primary and generated", () => Promise.all(connections.map(async connection => { // CockroachDB does not allow changing PK if (connection.driver instanceof CockroachDriver) return; @@ -130,9 +130,9 @@ describe("schema builder > change column", () => { idColumn.isGenerated = false; idColumn.generationStrategy = undefined; versionColumn.isPrimary = false; - })); + }))); - it("should correctly change column `isGenerated` property when column is on foreign key", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly change column `isGenerated` property when column is on foreign key", () => Promise.all(connections.map(async connection => { const teacherMetadata = connection.getMetadata("teacher"); const idColumn = teacherMetadata.findColumnWithPropertyName("id")!; idColumn.isGenerated = false; @@ -151,9 +151,9 @@ describe("schema builder > change column", () => { idColumn.isGenerated = true; idColumn.generationStrategy = "increment"; - })); + }))); - it("should correctly change non-generated column on to uuid-generated column", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly change non-generated column on to uuid-generated column", () => Promise.all(connections.map(async connection => { // CockroachDB does not allow changing PK if (connection.driver instanceof CockroachDriver) return; @@ -199,9 +199,9 @@ describe("schema builder > change column", () => { postMetadata.generatedColumns.splice(postMetadata.generatedColumns.indexOf(idColumn), 1); postMetadata.hasUUIDGeneratedColumns = false; - })); + }))); - it("should correctly change generated column generation strategy", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly change generated column generation strategy", () => Promise.all(connections.map(async connection => { // CockroachDB does not allow changing PK if (connection.driver instanceof CockroachDriver) return; @@ -246,6 +246,6 @@ describe("schema builder > change column", () => { idColumn.type = "int"; teacherColumn.type = "int"; - })); + }))); }); diff --git a/test/functional/schema-builder/change-exclusion-constraint.ts b/test/functional/schema-builder/change-exclusion-constraint.ts index c390f64dcf..dfd6366f74 100644 --- a/test/functional/schema-builder/change-exclusion-constraint.ts +++ b/test/functional/schema-builder/change-exclusion-constraint.ts @@ -1,7 +1,6 @@ import "reflect-metadata"; import {Connection} from "../../../src/connection/Connection"; import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; -import {PromiseUtils} from "../../../src"; import {Teacher} from "./entity/Teacher"; import {Post} from "./entity/Post"; import {ExclusionMetadata} from "../../../src/metadata/ExclusionMetadata"; @@ -20,7 +19,7 @@ describe("schema builder > change exclusion constraint", () => { beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); - it("should correctly add new exclusion constraint", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly add new exclusion constraint", () => Promise.all(connections.map(async connection => { const teacherMetadata = connection.getMetadata(Teacher); const exclusionMetadata = new ExclusionMetadata({ @@ -40,9 +39,9 @@ describe("schema builder > change exclusion constraint", () => { await queryRunner.release(); table!.exclusions.length.should.be.equal(1); - })); + }))); - it("should correctly change exclusion", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly change exclusion", () => Promise.all(connections.map(async connection => { const postMetadata = connection.getMetadata(Post); postMetadata.exclusions[0].expression = `USING gist ("tag" WITH =)`; @@ -55,9 +54,9 @@ describe("schema builder > change exclusion constraint", () => { await queryRunner.release(); table!.exclusions[0].expression!.indexOf("tag").should.be.not.equal(-1); - })); + }))); - it("should correctly drop removed exclusion", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly drop removed exclusion", () => Promise.all(connections.map(async connection => { const postMetadata = connection.getMetadata(Post); postMetadata.exclusions = []; @@ -69,6 +68,6 @@ describe("schema builder > change exclusion constraint", () => { await queryRunner.release(); table!.exclusions.length.should.be.equal(0); - })); + }))); }); diff --git a/test/functional/schema-builder/change-index.ts b/test/functional/schema-builder/change-index.ts index 47cb52a26d..0d8b9793a8 100644 --- a/test/functional/schema-builder/change-index.ts +++ b/test/functional/schema-builder/change-index.ts @@ -2,7 +2,6 @@ import "reflect-metadata"; import {Connection} from "../../../src/connection/Connection"; import {CockroachDriver} from "../../../src/driver/cockroachdb/CockroachDriver"; import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; -import {PromiseUtils} from "../../../src"; import {IndexMetadata} from "../../../src/metadata/IndexMetadata"; import {Teacher} from "./entity/Teacher"; import {Student} from "./entity/Student"; @@ -22,7 +21,7 @@ describe("schema builder > change index", () => { beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); - it("should correctly add new index", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly add new index", () => Promise.all(connections.map(async connection => { const teacherMetadata = connection.getMetadata(Teacher); const nameColumn = teacherMetadata.findColumnWithPropertyName("name")!; const indexMetadata = new IndexMetadata({ @@ -46,9 +45,9 @@ describe("schema builder > change index", () => { // revert changes teacherMetadata.indices.splice(teacherMetadata.indices.indexOf(indexMetadata), 1); - })); + }))); - it("should correctly change index", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly change index", () => Promise.all(connections.map(async connection => { const studentMetadata = connection.getMetadata(Student); studentMetadata.indices[0].name = "changed_index"; @@ -60,9 +59,9 @@ describe("schema builder > change index", () => { const index = studentTable!.indices.find(i => i.name === "changed_index"); expect(index).not.be.undefined; - })); + }))); - it("should correctly drop removed index", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly drop removed index", () => Promise.all(connections.map(async connection => { const studentMetadata = connection.getMetadata(Student); studentMetadata.indices.splice(0, 1); @@ -77,9 +76,9 @@ describe("schema builder > change index", () => { } else { studentTable!.indices.length.should.be.equal(0); } - })); + }))); - it("should ignore index synchronization when `synchronize` set to false", () => PromiseUtils.runInSequence(connections, async connection => { + it("should ignore index synchronization when `synchronize` set to false", () => Promise.all(connections.map(async connection => { // You can not disable synchronization for unique index in CockroachDB, because unique indices are stored as UNIQUE constraints @@ -116,6 +115,6 @@ describe("schema builder > change index", () => { await queryRunner.release(); - })); + }))); }); diff --git a/test/functional/schema-builder/change-unique-constraint.ts b/test/functional/schema-builder/change-unique-constraint.ts index dc020b8658..7791e24e9f 100644 --- a/test/functional/schema-builder/change-unique-constraint.ts +++ b/test/functional/schema-builder/change-unique-constraint.ts @@ -1,5 +1,4 @@ import "reflect-metadata"; -import {PromiseUtils} from "../../../src"; import {Connection} from "../../../src"; import {MysqlDriver} from "../../../src/driver/mysql/MysqlDriver"; import {SapDriver} from "../../../src/driver/sap/SapDriver"; @@ -23,7 +22,7 @@ describe("schema builder > change unique constraint", () => { beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); - it("should correctly add new unique constraint", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly add new unique constraint", () => Promise.all(connections.map(async connection => { const teacherMetadata = connection.getMetadata(Teacher); const nameColumn = teacherMetadata.findColumnWithPropertyName("name")!; let uniqueIndexMetadata: IndexMetadata|undefined = undefined; @@ -74,9 +73,9 @@ describe("schema builder > change unique constraint", () => { // revert changes teacherMetadata.uniques.splice(teacherMetadata.uniques.indexOf(uniqueMetadata!), 1); } - })); + }))); - it("should correctly change unique constraint", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly change unique constraint", () => Promise.all(connections.map(async connection => { // Sqlite does not store unique constraint name if (connection.driver instanceof AbstractSqliteDriver) return; @@ -116,9 +115,9 @@ describe("schema builder > change unique constraint", () => { uniqueMetadata!.name = connection.namingStrategy.uniqueConstraintName(table!, uniqueMetadata!.columns.map(c => c.databaseName)); } - })); + }))); - it("should correctly drop removed unique constraint", () => PromiseUtils.runInSequence(connections, async connection => { + it("should correctly drop removed unique constraint", () => Promise.all(connections.map(async connection => { const postMetadata = connection.getMetadata(Post); // Mysql and SAP stores unique constraints as unique indices. @@ -143,6 +142,6 @@ describe("schema builder > change unique constraint", () => { } else { table!.uniques.length.should.be.equal(1); } - })); + }))); }); diff --git a/test/functional/sqlite/enable-wal.ts b/test/functional/sqlite/enable-wal.ts new file mode 100644 index 0000000000..b1af701ebf --- /dev/null +++ b/test/functional/sqlite/enable-wal.ts @@ -0,0 +1,24 @@ +import "reflect-metadata"; +import {expect} from "chai"; +import {Connection} from "../../../src/connection/Connection"; +import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; + +describe("sqlite driver > enable wal", () => { + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [], + enabledDrivers: ["sqlite"], + driverSpecific: { + enableWAL: true + } + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should set the journal mode as expected", () => Promise.all(connections.map(async connection => { + // if we come this far, test was successful as a connection was established + const result = await connection.query('PRAGMA journal_mode'); + + expect(result).to.eql([{ journal_mode: 'wal'}]); + }))); +}); diff --git a/test/functional/table-inheritance/single-table/database-option-inherited/database-option-inherited.ts b/test/functional/table-inheritance/single-table/database-option-inherited/database-option-inherited.ts index 18700f5e11..66ba39cef9 100644 --- a/test/functional/table-inheritance/single-table/database-option-inherited/database-option-inherited.ts +++ b/test/functional/table-inheritance/single-table/database-option-inherited/database-option-inherited.ts @@ -8,7 +8,7 @@ describe("table-inheritance > single-table > database-option-inherited", () => { before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], // creating more databases isn't always possible(e.g oracle official docker images) - enabledDrivers: ["postgres", "cockroachdb", "mariadb", "mssql", "mysql", "sqlite", "sqljs"] + enabledDrivers: ["postgres", "cockroachdb", "mariadb", "mssql", "mysql", "sqlite", "better-sqlite3", "sqljs"] })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Faculty.ts b/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Faculty.ts new file mode 100644 index 0000000000..2a85a9ef8e --- /dev/null +++ b/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Faculty.ts @@ -0,0 +1,19 @@ +import {Column} from "../../../../../../../src/decorator/columns/Column"; +import {Entity} from "../../../../../../../src/decorator/entity/Entity"; +import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn"; +import {Staff} from "./Staff"; +import {OneToMany} from "../../../../../../../src"; + +@Entity() +export class Faculty { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + name: string; + + @OneToMany(type => Staff, staff => staff.faculty, { cascade: true, eager: true }) + staff: Staff[]; + +} diff --git a/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Professor.ts b/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Professor.ts new file mode 100644 index 0000000000..82c742be89 --- /dev/null +++ b/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Professor.ts @@ -0,0 +1,15 @@ +import {ChildEntity} from "../../../../../../../src/decorator/entity/ChildEntity"; +import {Staff} from "./Staff"; +import {Column} from "../../../../../../../src"; + +@ChildEntity("PROFESSOR") +export class Professor extends Staff { + + constructor(className: string) { + super(); + this.className = className; + } + + @Column() + className: string; +} diff --git a/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Researcher.ts b/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Researcher.ts new file mode 100644 index 0000000000..c85ff87a3f --- /dev/null +++ b/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Researcher.ts @@ -0,0 +1,15 @@ +import {ChildEntity} from "../../../../../../../src/decorator/entity/ChildEntity"; +import {Staff} from "./Staff"; +import {Column} from "../../../../../../../src"; + +@ChildEntity("RESEARCHER") +export class Researcher extends Staff { + + constructor(areaOfStudy: string) { + super(); + this.areaOfStudy = areaOfStudy; + } + + @Column() + areaOfStudy: string; +} diff --git a/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Staff.ts b/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Staff.ts new file mode 100644 index 0000000000..191e8ab950 --- /dev/null +++ b/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/entity/Staff.ts @@ -0,0 +1,17 @@ +import {Column, Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance} from "../../../../../../../src"; +import {Faculty} from "./Faculty"; + +@Entity() +@TableInheritance({ column: { name: "type", type: "varchar" } }) +export class Staff { + + @PrimaryGeneratedColumn() + id: number; + + @ManyToOne(type => Faculty, faculty => faculty.staff) + faculty: Faculty; + + @Column() + type: string; + +} diff --git a/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/one-to-many-cascade-save.ts b/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/one-to-many-cascade-save.ts new file mode 100644 index 0000000000..42d5c8631b --- /dev/null +++ b/test/functional/table-inheritance/single-table/relations/one-to-many-casecade-save/one-to-many-cascade-save.ts @@ -0,0 +1,42 @@ +import "reflect-metadata"; +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases +} from "../../../../../utils/test-utils"; +import {expect} from "chai"; +import {Connection} from "../../../../../../src/connection/Connection"; +import {Faculty} from "./entity/Faculty"; +import {Professor} from "./entity/Professor"; +import {Researcher} from "./entity/Researcher"; + +describe("table-inheritance > single-table > relations > one-to-many-cascade-save", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"] + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should work correctly with OneToMany relations", () => Promise.all(connections.map(async connection => { + + // ------------------------------------------------------------------------- + // Create + // ------------------------------------------------------------------------- + + const researcher = new Researcher("Economics"); + await connection.getRepository(Researcher).save(researcher); + + const faculty1 = new Faculty(); + faculty1.name = "Economics"; + faculty1.staff = [ new Professor("Economics 101"), researcher ]; + await connection.getRepository(Faculty).save(faculty1); + + const loadedFaculty = await connection.getRepository(Faculty).findOne() as Faculty; + + expect(loadedFaculty.staff.find(staff => staff.type === "PROFESSOR")).to.not.be.undefined; + expect(loadedFaculty.staff.find(staff => staff.type === "RESEARCHER")).to.not.be.undefined; + }))); + +}); diff --git a/test/functional/transaction/database-specific-isolation/sqlite-isolation.ts b/test/functional/transaction/database-specific-isolation/sqlite-isolation.ts index 907cb0da2d..9915e44415 100644 --- a/test/functional/transaction/database-specific-isolation/sqlite-isolation.ts +++ b/test/functional/transaction/database-specific-isolation/sqlite-isolation.ts @@ -10,7 +10,7 @@ describe("transaction > transaction with sqlite connection partial isolation sup let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"] // todo: for some reasons mariadb tests are not passing here + enabledDrivers: ["sqlite", "better-sqlite3"] // todo: for some reasons mariadb tests are not passing here })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/functional/transaction/return-data-from-transaction/return-data-from-transaction.ts b/test/functional/transaction/return-data-from-transaction/return-data-from-transaction.ts index db10856a45..55db390eb5 100644 --- a/test/functional/transaction/return-data-from-transaction/return-data-from-transaction.ts +++ b/test/functional/transaction/return-data-from-transaction/return-data-from-transaction.ts @@ -10,7 +10,7 @@ describe("transaction > return data from transaction", () => { let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mysql", "sqlite", "postgres"] // todo: for some reasons mariadb tests are not passing here + enabledDrivers: ["mysql", "sqlite", "better-sqlite3", "postgres"] // todo: for some reasons mariadb tests are not passing here })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/functional/transaction/single-query-runner/single-query-runner.ts b/test/functional/transaction/single-query-runner/single-query-runner.ts index 8a2339e811..2450f116f2 100644 --- a/test/functional/transaction/single-query-runner/single-query-runner.ts +++ b/test/functional/transaction/single-query-runner/single-query-runner.ts @@ -1,6 +1,6 @@ import "reflect-metadata"; import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils"; -import {Connection} from "../../../../src"; +import {Connection} from "../../../../src/connection/Connection"; import {Post} from "./entity/Post"; import {expect} from "chai"; diff --git a/test/functional/transaction/transaction-in-entity-manager/transaction-in-entity-manager.ts b/test/functional/transaction/transaction-in-entity-manager/transaction-in-entity-manager.ts index 9b20840dc9..a47c9d7fbd 100644 --- a/test/functional/transaction/transaction-in-entity-manager/transaction-in-entity-manager.ts +++ b/test/functional/transaction/transaction-in-entity-manager/transaction-in-entity-manager.ts @@ -10,7 +10,7 @@ describe("transaction > transaction with entity manager", () => { let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mysql", "sqlite", "postgres"] // todo: for some reasons mariadb tests are not passing here + enabledDrivers: ["mysql", "sqlite", "better-sqlite3", "postgres"] // todo: for some reasons mariadb tests are not passing here })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/functional/uuid/sqlite/uuid-sqlite.ts b/test/functional/uuid/sqlite/uuid-sqlite.ts index f167faee6d..ee03f28e3b 100644 --- a/test/functional/uuid/sqlite/uuid-sqlite.ts +++ b/test/functional/uuid/sqlite/uuid-sqlite.ts @@ -11,7 +11,7 @@ describe("uuid-sqlite", () => { before(async () => { connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"], + enabledDrivers: ["sqlite", "better-sqlite3"], }); }); beforeEach(() => reloadTestingDatabases(connections)); diff --git a/test/functional/view-entity/general/entity/PhotoAlbumCategory.ts b/test/functional/view-entity/general/entity/PhotoAlbumCategory.ts index 1fea2be7ea..7bd97279d8 100644 --- a/test/functional/view-entity/general/entity/PhotoAlbumCategory.ts +++ b/test/functional/view-entity/general/entity/PhotoAlbumCategory.ts @@ -9,6 +9,7 @@ import {Photo} from "./Photo"; expression: (connection: Connection) => connection.createQueryBuilder() .select("photo.id", "id") .addSelect("photo.name", "name") + .addSelect("photo.albumId", "albumId") .addSelect("category.name", "categoryName") .addSelect("album.name", "albumName") .from(Photo, "photo") @@ -29,4 +30,7 @@ export class PhotoAlbumCategory { @ViewColumn() albumName: string; + + @ViewColumn({ name: "albumId" }) + photoAlbumId: number; } diff --git a/test/functional/view-entity/general/view-entity-general.ts b/test/functional/view-entity/general/view-entity-general.ts index e91e638b4b..dfffd78684 100644 --- a/test/functional/view-entity/general/view-entity-general.ts +++ b/test/functional/view-entity/general/view-entity-general.ts @@ -104,6 +104,7 @@ describe("view entity > general", () => { photoAlbumCategory!.name.should.be.equal("BMW E39"); photoAlbumCategory!.albumName.should.be.equal("BMW photos"); photoAlbumCategory!.categoryName.should.be.equal("Cars"); + photoAlbumCategory!.photoAlbumId.should.be.equal(1); }))); }); diff --git a/test/functional/view-entity/mssql/entity/PostCategory.ts b/test/functional/view-entity/mssql/entity/PostCategory.ts index d3540166e2..975d5d83d2 100644 --- a/test/functional/view-entity/mssql/entity/PostCategory.ts +++ b/test/functional/view-entity/mssql/entity/PostCategory.ts @@ -11,8 +11,8 @@ export class PostCategory { @ViewColumn() id: number; - @ViewColumn() - name: string; + @ViewColumn({ name: "name" }) + postName: string; @ViewColumn() categoryName: string; diff --git a/test/functional/view-entity/mssql/view-entity-mssql.ts b/test/functional/view-entity/mssql/view-entity-mssql.ts index 90b1fc86c1..451d8aeff7 100644 --- a/test/functional/view-entity/mssql/view-entity-mssql.ts +++ b/test/functional/view-entity/mssql/view-entity-mssql.ts @@ -49,11 +49,11 @@ describe("view entity > mssql", () => { postCategories.length.should.be.equal(2); postCategories[0].id.should.be.equal(1); - postCategories[0].name.should.be.equal("About BMW"); + postCategories[0].postName.should.be.equal("About BMW"); postCategories[0].categoryName.should.be.equal("Cars"); postCategories[1].id.should.be.equal(2); - postCategories[1].name.should.be.equal("About Boeing"); + postCategories[1].postName.should.be.equal("About Boeing"); postCategories[1].categoryName.should.be.equal("Airplanes"); }))); diff --git a/test/functional/view-entity/mysql/entity/PostCategory.ts b/test/functional/view-entity/mysql/entity/PostCategory.ts index 4b1df7d531..24be89ec28 100644 --- a/test/functional/view-entity/mysql/entity/PostCategory.ts +++ b/test/functional/view-entity/mysql/entity/PostCategory.ts @@ -11,8 +11,8 @@ export class PostCategory { @ViewColumn() id: number; - @ViewColumn() - name: string; + @ViewColumn({ name: "name" }) + postName: string; @ViewColumn() categoryName: string; diff --git a/test/functional/view-entity/mysql/view-entity-mysql.ts b/test/functional/view-entity/mysql/view-entity-mysql.ts index 2a90445b27..0e8ca35a75 100644 --- a/test/functional/view-entity/mysql/view-entity-mysql.ts +++ b/test/functional/view-entity/mysql/view-entity-mysql.ts @@ -49,11 +49,11 @@ describe("view entity > mysql", () => { postCategories.length.should.be.equal(2); postCategories[0].id.should.be.equal(1); - postCategories[0].name.should.be.equal("About BMW"); + postCategories[0].postName.should.be.equal("About BMW"); postCategories[0].categoryName.should.be.equal("Cars"); postCategories[1].id.should.be.equal(2); - postCategories[1].name.should.be.equal("About Boeing"); + postCategories[1].postName.should.be.equal("About Boeing"); postCategories[1].categoryName.should.be.equal("Airplanes"); }))); diff --git a/test/functional/view-entity/oracle/entity/PostCategory.ts b/test/functional/view-entity/oracle/entity/PostCategory.ts index d3540166e2..975d5d83d2 100644 --- a/test/functional/view-entity/oracle/entity/PostCategory.ts +++ b/test/functional/view-entity/oracle/entity/PostCategory.ts @@ -11,8 +11,8 @@ export class PostCategory { @ViewColumn() id: number; - @ViewColumn() - name: string; + @ViewColumn({ name: "name" }) + postName: string; @ViewColumn() categoryName: string; diff --git a/test/functional/view-entity/oracle/view-entity-oracle.ts b/test/functional/view-entity/oracle/view-entity-oracle.ts index 03c4f650a8..620cd11e00 100644 --- a/test/functional/view-entity/oracle/view-entity-oracle.ts +++ b/test/functional/view-entity/oracle/view-entity-oracle.ts @@ -49,11 +49,11 @@ describe("view entity > oracle", () => { postCategories.length.should.be.equal(2); postCategories[0].id.should.be.equal(1); - postCategories[0].name.should.be.equal("About BMW"); + postCategories[0].postName.should.be.equal("About BMW"); postCategories[0].categoryName.should.be.equal("Cars"); postCategories[1].id.should.be.equal(2); - postCategories[1].name.should.be.equal("About Boeing"); + postCategories[1].postName.should.be.equal("About Boeing"); postCategories[1].categoryName.should.be.equal("Airplanes"); }))); diff --git a/test/functional/view-entity/postgres/entity/PostCategory.ts b/test/functional/view-entity/postgres/entity/PostCategory.ts index d3540166e2..975d5d83d2 100644 --- a/test/functional/view-entity/postgres/entity/PostCategory.ts +++ b/test/functional/view-entity/postgres/entity/PostCategory.ts @@ -11,8 +11,8 @@ export class PostCategory { @ViewColumn() id: number; - @ViewColumn() - name: string; + @ViewColumn({ name: "name" }) + postName: string; @ViewColumn() categoryName: string; diff --git a/test/functional/view-entity/postgres/view-entity-postgres.ts b/test/functional/view-entity/postgres/view-entity-postgres.ts index 9883e66d63..eb56de2e71 100644 --- a/test/functional/view-entity/postgres/view-entity-postgres.ts +++ b/test/functional/view-entity/postgres/view-entity-postgres.ts @@ -75,11 +75,11 @@ describe("view entity > postgres", () => { postCategories.length.should.be.equal(2); postCategories[0].id.should.be.equal(1); - postCategories[0].name.should.be.equal("About BMW"); + postCategories[0].postName.should.be.equal("About BMW"); postCategories[0].categoryName.should.be.equal("Cars"); postCategories[1].id.should.be.equal(2); - postCategories[1].name.should.be.equal("About Boeing"); + postCategories[1].postName.should.be.equal("About Boeing"); postCategories[1].categoryName.should.be.equal("Airplanes"); }))); diff --git a/test/functional/view-entity/sqlite/entity/PostCategory.ts b/test/functional/view-entity/sqlite/entity/PostCategory.ts index d3540166e2..975d5d83d2 100644 --- a/test/functional/view-entity/sqlite/entity/PostCategory.ts +++ b/test/functional/view-entity/sqlite/entity/PostCategory.ts @@ -11,8 +11,8 @@ export class PostCategory { @ViewColumn() id: number; - @ViewColumn() - name: string; + @ViewColumn({ name: "name" }) + postName: string; @ViewColumn() categoryName: string; diff --git a/test/functional/view-entity/sqlite/view-entity-sqlite.ts b/test/functional/view-entity/sqlite/view-entity-sqlite.ts index 1a3423b385..3fe63aa72e 100644 --- a/test/functional/view-entity/sqlite/view-entity-sqlite.ts +++ b/test/functional/view-entity/sqlite/view-entity-sqlite.ts @@ -11,7 +11,7 @@ describe("view entity > sqlite", () => { let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"] + enabledDrivers: ["sqlite", "better-sqlite3"] })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); @@ -49,11 +49,11 @@ describe("view entity > sqlite", () => { postCategories.length.should.be.equal(2); postCategories[0].id.should.be.equal(1); - postCategories[0].name.should.be.equal("About BMW"); + postCategories[0].postName.should.be.equal("About BMW"); postCategories[0].categoryName.should.be.equal("Cars"); postCategories[1].id.should.be.equal(2); - postCategories[1].name.should.be.equal("About Boeing"); + postCategories[1].postName.should.be.equal("About Boeing"); postCategories[1].categoryName.should.be.equal("Airplanes"); }))); diff --git a/test/github-issues/1014/issue-1014.ts b/test/github-issues/1014/issue-1014.ts index b9e8f37399..787e9e878f 100644 --- a/test/github-issues/1014/issue-1014.ts +++ b/test/github-issues/1014/issue-1014.ts @@ -3,7 +3,6 @@ import {closeTestingConnections, createTestingConnections, reloadTestingDatabase import {Connection} from "../../../src/connection/Connection"; import {TestEntity} from "./entity/TestEntity"; import {expect} from "chai"; -import {PromiseUtils} from "../../../src/util/PromiseUtils"; describe("github issues > #1014 Transaction doesn't rollback", () => { @@ -18,16 +17,14 @@ describe("github issues > #1014 Transaction doesn't rollback", () => { const testEntity = new TestEntity(); testEntity.name = "Hello Test"; - await connection.manager.save(testEntity); + await connection.manager.save(testEntity, { reload: true }); let error: any; try { - await connection.transaction(manager => { - return PromiseUtils.settle([ - manager.remove(TestEntity, { id: 1 } as TestEntity), - Promise.reject(new Error()), - new Promise((resolve, reject) => reject(new Error())), - ]); + await connection.transaction(async manager => { + await manager.remove(testEntity); + + throw new Error(); }); } catch (err) { error = err; } diff --git a/test/github-issues/1055/issue-1055.ts b/test/github-issues/1055/issue-1055.ts index 8572889e12..dc429e7c25 100644 --- a/test/github-issues/1055/issue-1055.ts +++ b/test/github-issues/1055/issue-1055.ts @@ -41,32 +41,6 @@ describe("github issues > #1055 ind with relations not working, correct syntax c expect(foundChild).not.to.be.undefined; }))); - - it("should be able to lookup from promise as well", () => Promise.all(connections.map(async connection => { - const manager = connection.manager; - - const parent = new Parent(); - parent.name = "Parent"; - await manager.save(parent); - - const loadedParent = await manager.findOne(Parent, 1); - expect(loadedParent).not.to.be.undefined; - - if (!loadedParent) return; - - const child = new Child(); - child.name = "Child"; - child.parent = Promise.resolve(loadedParent); - await manager.save(child); - - const foundChild = await manager.findOne(Child, { - parent: { - id: loadedParent.id - } - }); - expect(foundChild).not.to.be.undefined; - }))); - it("should not have type errors with the primary key type", () => Promise.all(connections.map(async connection => { const manager = connection.manager; diff --git a/test/github-issues/1123/issue-1123.ts b/test/github-issues/1123/issue-1123.ts index 510055f708..cfd78b1749 100644 --- a/test/github-issues/1123/issue-1123.ts +++ b/test/github-issues/1123/issue-1123.ts @@ -55,9 +55,9 @@ describe("github issues > #1123 load relation eagerly by setting isEager propert .createQueryBuilder("Post", "post") .where("post.id = :id", { id: 1 }) .disableEagerRelations() - .getOne(); + .getOne() as Post; - (loadedPost as Post).should.be.eql({ + loadedPost!.should.be.eql({ id: 1, title: "Post 1" }); diff --git a/test/github-issues/114/issue-114.ts b/test/github-issues/114/issue-114.ts index 0bf45946e2..f3a322fb5c 100644 --- a/test/github-issues/114/issue-114.ts +++ b/test/github-issues/114/issue-114.ts @@ -7,7 +7,7 @@ describe.skip("github issues > #114 Can not be parsed correctly the URL of pg.", let connection: Connection; before(() => { - connection = new Connection({ + connection = new Connection({ // Dummy Connection, won't be established type: "postgres", url: "postgres://test:test@localhost:5432/test", }); diff --git a/test/github-issues/1261/issue-1261.ts b/test/github-issues/1261/issue-1261.ts index 0a1431ab4d..db374143e2 100644 --- a/test/github-issues/1261/issue-1261.ts +++ b/test/github-issues/1261/issue-1261.ts @@ -1,9 +1,7 @@ import "reflect-metadata"; import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils"; import {Connection} from "../../../src/connection/Connection"; -import {BaseEntity} from "../../../src/repository/BaseEntity"; import {Bar} from "./entity/Bar"; -import {PromiseUtils} from "../../../src"; describe("github issues > #1261 onDelete property on foreign key is not modified on sync", () => { @@ -13,10 +11,8 @@ describe("github issues > #1261 onDelete property on foreign key is not modified })); after(() => closeTestingConnections(connections)); - it("should modify onDelete property on foreign key on sync", () => PromiseUtils.runInSequence(connections, async connection => { - + it("should modify onDelete property on foreign key on sync", () => Promise.all(connections.map(async connection => { await connection.synchronize(); - BaseEntity.useConnection(connection); const queryRunner = connection.createQueryRunner(); let table = await queryRunner.getTable("bar"); @@ -31,6 +27,6 @@ describe("github issues > #1261 onDelete property on foreign key is not modified await queryRunner.release(); - })); + }))); }); diff --git a/test/github-issues/134/issue-134.ts b/test/github-issues/134/issue-134.ts index 8a364197fc..1b4b8e1e2c 100644 --- a/test/github-issues/134/issue-134.ts +++ b/test/github-issues/134/issue-134.ts @@ -9,7 +9,7 @@ describe("github issues > #134 Error TIME is converted to 'HH-mm' instead of 'HH let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mysql", "mariadb", "sqlite", "mssql", "postgres"] // Oracle does not support TIME data type. + enabledDrivers: ["mysql", "mariadb", "sqlite", "better-sqlite3", "mssql", "postgres"] // Oracle does not support TIME data type. })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/github-issues/1465/save-relation.ts b/test/github-issues/1465/save-relation.ts index bd5ef09067..e0ee4f0ce2 100644 --- a/test/github-issues/1465/save-relation.ts +++ b/test/github-issues/1465/save-relation.ts @@ -10,7 +10,7 @@ describe("save child and parent entity", () => { let connections: Connection[] = []; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mysql", "mariadb", "sqlite", "sqljs"] + enabledDrivers: ["mysql", "mariadb", "sqlite", "better-sqlite3", "sqljs"] })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/github-issues/1476/issue-1476.ts b/test/github-issues/1476/issue-1476.ts index b886071a40..7b73d5b468 100644 --- a/test/github-issues/1476/issue-1476.ts +++ b/test/github-issues/1476/issue-1476.ts @@ -12,7 +12,7 @@ describe("github issues > #1476 subqueries", () => { let connections: Connection[] = []; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mysql", "mariadb", "sqlite", "sqljs"] + enabledDrivers: ["mysql", "mariadb", "sqlite", "better-sqlite3", "sqljs"] })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/github-issues/1545/entity/DataModel.ts b/test/github-issues/1545/entity/DataModel.ts index b89a133080..6ca033cc1a 100644 --- a/test/github-issues/1545/entity/DataModel.ts +++ b/test/github-issues/1545/entity/DataModel.ts @@ -3,6 +3,7 @@ import {MainModel} from "./MainModel"; import {ValidationModel} from "./ValidationModel"; import {PrimaryColumn} from "../../../../src/decorator/columns/PrimaryColumn"; + @Entity() export class DataModel { @@ -18,17 +19,17 @@ export class DataModel { @PrimaryColumn() mainId: number; - + @ManyToOne(type => MainModel) @JoinColumn({ name: "mainId", referencedColumnName: "id" }) main: MainModel; - + @Column({ type: "boolean", default: false }) active: boolean; -} \ No newline at end of file +} diff --git a/test/github-issues/1576/issue-1576.ts b/test/github-issues/1576/issue-1576.ts index 5b0d76adcc..4bb570ddc0 100644 --- a/test/github-issues/1576/issue-1576.ts +++ b/test/github-issues/1576/issue-1576.ts @@ -24,9 +24,6 @@ describe("github issues > #1576 Entities with null as `id` are merged [@next]", newpost.categories = [cat1, cat2]; const post = connection.manager.create(Post, newpost); - // connection.manager.create(Post, { - // categories: cats - // }); expect(post.categories).to.have.length(2); }))); diff --git a/test/github-issues/1591/issue-1591.ts b/test/github-issues/1591/issue-1591.ts index 5472b9d84b..4b7feaaf60 100644 --- a/test/github-issues/1591/issue-1591.ts +++ b/test/github-issues/1591/issue-1591.ts @@ -40,6 +40,7 @@ describe("github issues > #1591 Define order of relation data when querying on t .skip(0) .take(5) .getMany(); + }))); }); diff --git a/test/github-issues/1805/issue-1805.ts b/test/github-issues/1805/issue-1805.ts index a1cc57b95a..6d734cad03 100644 --- a/test/github-issues/1805/issue-1805.ts +++ b/test/github-issues/1805/issue-1805.ts @@ -2,7 +2,6 @@ import "reflect-metadata"; import {Connection} from "../../../src/connection/Connection"; import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils"; import {Account} from "./entity/Account"; -import {PromiseUtils} from "../../../src"; describe("github issues > #1805 bigint PK incorrectly returning as a number (expecting a string)", () => { @@ -17,16 +16,17 @@ describe("github issues > #1805 bigint PK incorrectly returning as a number (exp }); after(() => closeTestingConnections(connections)); - it("should return `bigint` column as string", () => PromiseUtils.runInSequence(connections, async connection => { - Account.useConnection(connection); - let account: Account|undefined; + it("should return `bigint` column as string", () => Promise.all(connections.map(async connection => { const bigIntId = "76561198016705746"; - account = new Account(); + const account = new Account(); account.id = bigIntId; - await account.save(); - account = await Account.findOne(bigIntId); - account!.id.should.be.equal(bigIntId); - })); + const accountRepository = await connection.getRepository(Account); + + await accountRepository.save(account); + + const loadedAccount = await accountRepository.findOne(bigIntId); + loadedAccount!.id.should.be.equal(bigIntId); + }))); }); diff --git a/test/github-issues/1898/issue-1898.ts b/test/github-issues/1898/issue-1898.ts index a591d7c1ae..3eac414962 100644 --- a/test/github-issues/1898/issue-1898.ts +++ b/test/github-issues/1898/issue-1898.ts @@ -9,7 +9,7 @@ describe("github issues > #1898 Simple JSON breaking in @next", () => { before(async () => { connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"], + enabledDrivers: ["sqlite", "better-sqlite3"], schemaCreate: true, dropSchema: true }); diff --git a/test/github-issues/190/issue-190.ts b/test/github-issues/190/issue-190.ts index 665b3ab5c8..ab7f397027 100644 --- a/test/github-issues/190/issue-190.ts +++ b/test/github-issues/190/issue-190.ts @@ -8,7 +8,7 @@ describe("github issues > #190 too many SQL variables when using setMaxResults i let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"] // this issue only related to sqlite + enabledDrivers: ["sqlite", "better-sqlite3"] // this issue only related to sqlite })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/github-issues/1960/issue-1960.ts b/test/github-issues/1960/issue-1960.ts index ed09a876ab..bf9c10c640 100644 --- a/test/github-issues/1960/issue-1960.ts +++ b/test/github-issues/1960/issue-1960.ts @@ -8,7 +8,7 @@ describe.skip("github issues > #1960 Migration generator produces duplicated cha let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mysql"], + enabledDrivers: ["mysql"] })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/github-issues/1972/issue-1972.ts b/test/github-issues/1972/issue-1972.ts index 181c767e22..01391658c5 100644 --- a/test/github-issues/1972/issue-1972.ts +++ b/test/github-issues/1972/issue-1972.ts @@ -10,6 +10,7 @@ describe("github issues > #1972 STI problem - empty columns", () => { before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], + enabledDrivers: ['mysql'] })); beforeEach(() => reloadTestingDatabases(connections)); diff --git a/test/github-issues/1981/issue-1981.ts b/test/github-issues/1981/issue-1981.ts index 1134f42d75..3e653ec0cf 100644 --- a/test/github-issues/1981/issue-1981.ts +++ b/test/github-issues/1981/issue-1981.ts @@ -7,7 +7,7 @@ describe("github issues > #1981 Boolean values not casted properly when used in let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"], + enabledDrivers: ["sqlite", "better-sqlite3"], })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/github-issues/2005/issue-2005.ts b/test/github-issues/2005/issue-2005.ts index 52aaf9eb3e..bb714b3158 100644 --- a/test/github-issues/2005/issue-2005.ts +++ b/test/github-issues/2005/issue-2005.ts @@ -7,7 +7,7 @@ describe("github issues > #2005", () => { let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"] + enabledDrivers: ["sqlite", "better-sqlite3"] })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/github-issues/2044/issue-2044.ts b/test/github-issues/2044/issue-2044.ts index 97d5d48700..f6aa3ce3b5 100644 --- a/test/github-issues/2044/issue-2044.ts +++ b/test/github-issues/2044/issue-2044.ts @@ -38,4 +38,4 @@ describe("github issues > #2044 Should not double get embedded column value", () resultPhoto.user.id.should.be.eql(userId); }))); -}); \ No newline at end of file +}); diff --git a/test/github-issues/2096/entity/TestEntity.ts b/test/github-issues/2096/entity/TestEntity.ts new file mode 100644 index 0000000000..355ba71f11 --- /dev/null +++ b/test/github-issues/2096/entity/TestEntity.ts @@ -0,0 +1,9 @@ +import {Entity, PrimaryGeneratedColumn} from "../../../../src"; + +@Entity() +export class TestEntity { + + @PrimaryGeneratedColumn() + id: number; + +} diff --git a/test/github-issues/2096/issue-2096.ts b/test/github-issues/2096/issue-2096.ts new file mode 100644 index 0000000000..768f48b17b --- /dev/null +++ b/test/github-issues/2096/issue-2096.ts @@ -0,0 +1,37 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import { createConnection } from "../../../src"; +import { getTypeOrmConfig } from "../../utils/test-utils"; +import {MysqlConnectionOptions} from "../../../src/driver/mysql/MysqlConnectionOptions"; + +describe("github issues > #2096 [mysql] Database name isn't read from url", () => { + it("should be possible to define a database by connection url for mysql", async () => { + const config = getTypeOrmConfig(); + + // it is important to synchronize here, to trigger EntityMetadataValidator.validate + // that previously threw the error where the database on the driver object was undefined + const mysqlConfig: MysqlConnectionOptions = config.find(c => c.name === "mysql" && !c.skip) as MysqlConnectionOptions; + + if (mysqlConfig) { + const { + username, + password, + host, + port, + database + } = mysqlConfig; + + const url = `mysql://${username}:${password}@${host}:${port}/${database}` + + const connection = await createConnection({ + name: "#2096", + url, + entities: [__dirname + "/entity/*{.js,.ts}"], + synchronize: true, + type: "mysql" + }); + expect(connection.isConnected).to.eq(true); + await connection.close(); + } + }); +}); diff --git a/test/github-issues/2131/entity/Post.ts b/test/github-issues/2131/entity/Post.ts new file mode 100644 index 0000000000..2004a60966 --- /dev/null +++ b/test/github-issues/2131/entity/Post.ts @@ -0,0 +1,12 @@ +import { PrimaryGeneratedColumn, Entity, Column } from "../../../../src"; + +@Entity() +export class Post { + + @PrimaryGeneratedColumn() + id: number | null; + + @Column() + title: string; + +} diff --git a/test/github-issues/2131/issue-2131.ts b/test/github-issues/2131/issue-2131.ts new file mode 100644 index 0000000000..6d67a4aaf8 --- /dev/null +++ b/test/github-issues/2131/issue-2131.ts @@ -0,0 +1,53 @@ +import "reflect-metadata"; +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases, +} from "../../utils/test-utils"; +import { Connection } from "../../../src/connection/Connection"; +import { expect } from "chai"; +import { Post } from "./entity/Post"; + +describe("github issues > #2131 InsertResult return the same primary key", () => { + let connections: Connection[]; + const posts: Post[] = [{ + id: null, + title: "Post 1", + }, { + id: null, + title: "Post 2", + }, { + id: null, + title: "Post 3", + }, { + id: null, + title: "Post 4", + }]; + + before( + async () => + (connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + enabledDrivers: ["sqlite", "mysql"], + })) + ); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should get correct insert ids for multiple entities inserted", () => + Promise.all( + connections.map(async (connection) => { + await connection + .createQueryBuilder() + .insert() + .into(Post) + .values(posts) + .execute(); + + expect(posts[0].id).to.equal(1); + expect(posts[1].id).to.equal(2); + expect(posts[2].id).to.equal(3); + expect(posts[3].id).to.equal(4); + }) + )); +}); diff --git a/test/github-issues/2199/issue-2199.ts b/test/github-issues/2199/issue-2199.ts index 3898c9f36f..8a51691ac9 100644 --- a/test/github-issues/2199/issue-2199.ts +++ b/test/github-issues/2199/issue-2199.ts @@ -9,7 +9,7 @@ describe("github issues > #2199 - Inserting value for @PrimaryGeneratedColumn() let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mysql", "mariadb", "sqlite"], + enabledDrivers: ["mysql", "mariadb", "sqlite", "better-sqlite3"], schemaCreate: true, dropSchema: true })); diff --git a/test/github-issues/2216/entity/Foo.ts b/test/github-issues/2216/entity/Foo.ts new file mode 100644 index 0000000000..d7e2038db8 --- /dev/null +++ b/test/github-issues/2216/entity/Foo.ts @@ -0,0 +1,16 @@ +import { + Column, + Entity, + PrimaryGeneratedColumn, +} from "../../../../src"; + +@Entity("foo") +export class Foo { + @PrimaryGeneratedColumn("uuid") public uuid: string; + + @Column({ type: "citext", nullable: false }) + public lowercaseval: string; + + @Column({ type: "citext", nullable: false }) + public lowercaseval2: string; +} diff --git a/test/github-issues/2216/issue-2216.ts b/test/github-issues/2216/issue-2216.ts new file mode 100644 index 0000000000..3cb4287d9f --- /dev/null +++ b/test/github-issues/2216/issue-2216.ts @@ -0,0 +1,130 @@ +import sinon from "sinon"; +import {Connection} from "../../../src/connection/Connection"; +import {createTestingConnections, closeTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; +import { EntityManager, QueryRunner, SimpleConsoleLogger } from "../../../src"; +import { Foo } from "./entity/Foo"; +import { expect } from "chai"; + +describe("github issues > #2216 - Ability to capture Postgres notifications in logger", () => { + let connections: Connection[]; + let queryRunner: QueryRunner; + let manager: EntityManager; + let logInfoStub: sinon.SinonStub; + + before(() => { + logInfoStub = sinon.stub(SimpleConsoleLogger.prototype, "log"); + }); + beforeEach(async () => { + await reloadTestingDatabases(connections); + }); + afterEach(() => logInfoStub.resetHistory()); + after(() => logInfoStub.restore()); + + describe("when logNotifications option is NOT enabled", () => { + before(async () => { + connections = await createTestingConnections({ + enabledDrivers: ["postgres"], + entities: [Foo], + logging: true, + createLogger: () => new SimpleConsoleLogger(), + }); + }); + after(() => closeTestingConnections(connections)); + + it("should NOT pass extension setup notices to client", async () => Promise.all(connections.map(async connection => { + sinon.assert.neverCalledWith( + logInfoStub, + "info", + `extension "uuid-ossp" already exists, skipping` + ); + sinon.assert.neverCalledWith( + logInfoStub, + "info", + `extension "citext" already exists, skipping` + ); + }))); + + it("should NOT pass manual notices to client", async () => Promise.all(connections.map(async connection => { + queryRunner = connection.createQueryRunner(); + await queryRunner.query(`DO $do$ BEGIN RAISE NOTICE 'this is a notice'; END $do$`); + sinon.assert.neverCalledWith( + logInfoStub, + "info", + "this is a notice" + ); + await queryRunner.release(); + }))); + + it("should NOT pass 'listen -> notify' messages to client", async () => Promise.all(connections.map(async connection => { + queryRunner = connection.createQueryRunner(); + await queryRunner.query("LISTEN foo;"); + await queryRunner.query("NOTIFY foo, 'bar!'"); + sinon.assert.neverCalledWith( + logInfoStub, + "info", + "Received NOTIFY on channel foo: bar!." + ); + await queryRunner.release(); + }))); + }); + + describe("when logNotifications option is enabled", () => { + before(async () => { + connections = await createTestingConnections({ + enabledDrivers: ["postgres"], + entities: [Foo], + logging: true, + createLogger: () => new SimpleConsoleLogger(), + driverSpecific: { logNotifications: true }, + }); + }); + after(() => closeTestingConnections(connections)); + + it("should pass extension setup notices to client", async () => Promise.all(connections.map(async connection => { + sinon.assert.calledWith( + logInfoStub, + "info", + `extension "uuid-ossp" already exists, skipping` + ); + sinon.assert.calledWith( + logInfoStub, + "info", + `extension "citext" already exists, skipping` + ); + }))); + + it("should pass manual notices to client", async () => Promise.all(connections.map(async connection => { + queryRunner = connection.createQueryRunner(); + await queryRunner.query(`DO $do$ BEGIN RAISE NOTICE 'this is a notice'; END $do$`); + sinon.assert.calledWith( + logInfoStub, + "info", + "this is a notice" + ); + await queryRunner.release(); + }))); + + it("should pass 'listen -> notify' messages to client", async () => Promise.all(connections.map(async connection => { + queryRunner = connection.createQueryRunner(); + await queryRunner.query("LISTEN foo;"); + await queryRunner.query("NOTIFY foo, 'bar!'"); + sinon.assert.calledWith( + logInfoStub, + "info", + "Received NOTIFY on channel foo: bar!." + ); + await queryRunner.release(); + }))); + + it("should not interfere with actual queries", async () => Promise.all(connections.map(async connection => { + manager = connection.manager; + await manager.save(Object.assign(new Foo(), { lowercaseval: "foo", lowercaseval2: "bar"})); + const loadedFoo = await manager.findOne(Foo); + expect(loadedFoo).not.to.be.undefined; + expect(loadedFoo).to.contain({ + lowercaseval: "foo", + lowercaseval2: "bar", + }); + }))); + }); +}); diff --git a/test/github-issues/2313/issue-2313.ts b/test/github-issues/2313/issue-2313.ts index fda6ff7033..b5b98f0eeb 100644 --- a/test/github-issues/2313/issue-2313.ts +++ b/test/github-issues/2313/issue-2313.ts @@ -1,6 +1,5 @@ import "reflect-metadata"; import {Connection} from "../../../src/connection/Connection"; -import {PromiseUtils} from "../../../src/util/PromiseUtils"; import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; import {Post} from "./entity/Post"; import {expect} from "chai"; @@ -16,35 +15,41 @@ describe("github issues > #2313 - BaseEntity has no findOneOrFail() method", () beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); - it("should find the appropriate record when one exists", () => PromiseUtils.runInSequence(connections, async connection => { - Post.useConnection(connection); // change connection each time because of AR specifics + it("should find the appropriate record when one exists", async () => { + // These must run sequentially as we have the global context of the `Post` ActiveRecord class + for (const connection of connections) { + Post.useConnection(connection); // change connection each time because of AR specifics - const post1 = new Post(); - post1.data = 123; - await post1.save(); + const post1 = new Post(); + post1.data = 123; + await post1.save(); - const post2 = new Post(); - post2.data = 456; - await post2.save(); + const post2 = new Post(); + post2.data = 456; + await post2.save(); - const result1 = await Post.findOneOrFail(1); + const result1 = await Post.findOneOrFail(1); - result1.data.should.be.eql(123); + result1.data.should.be.eql(123); - const result2 = await Post.findOneOrFail(2); + const result2 = await Post.findOneOrFail(2); - result2.data.should.be.eql(456); - })); - - it("should throw no matching record exists", () => PromiseUtils.runInSequence(connections, async connection => { - Post.useConnection(connection); // change connection each time because of AR specifics - - try { - await Post.findOneOrFail(100); - expect.fail(); - } catch (e) { - e.should.be.instanceOf(EntityNotFoundError); + result2.data.should.be.eql(456); } - })); + }); + + it("should throw no matching record exists", async () => { + // These must run sequentially as we have the global context of the `Post` ActiveRecord class + for (const connection of connections) { + Post.useConnection(connection); // change connection each time because of AR specifics + + try { + await Post.findOneOrFail(100); + expect.fail(); + } catch (e) { + e.should.be.instanceOf(EntityNotFoundError); + } + } + }); }); diff --git a/test/github-issues/2518/issue-2518.ts b/test/github-issues/2518/issue-2518.ts index 538f1ee466..8b451aba25 100644 --- a/test/github-issues/2518/issue-2518.ts +++ b/test/github-issues/2518/issue-2518.ts @@ -12,7 +12,7 @@ describe("github issues > #2518 TreeRepository.findDescendantsTree does not load (connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], // data type text isn't compatible with oracle - enabledDrivers: ["postgres", "cockroachdb", "mariadb", "mssql", "mysql", "sqlite", "sqljs"] + enabledDrivers: ["postgres", "cockroachdb", "mariadb", "mssql", "mysql", "sqlite", "better-sqlite3", "sqljs"] })) ); diff --git a/test/github-issues/2703/entity/Dummy.ts b/test/github-issues/2703/entity/Dummy.ts new file mode 100644 index 0000000000..a2354cd51c --- /dev/null +++ b/test/github-issues/2703/entity/Dummy.ts @@ -0,0 +1,13 @@ +import {Entity} from "../../../../src/decorator/entity/Entity"; +import {Column} from "../../../../src/decorator/columns/Column"; +import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn"; +import {WrappedString, wrappedStringTransformer} from "../wrapped-string"; + +@Entity() +export class Dummy { + @PrimaryGeneratedColumn() + id: number; + + @Column({type: String, transformer: wrappedStringTransformer}) + value: WrappedString; +} diff --git a/test/github-issues/2703/issue-2703.ts b/test/github-issues/2703/issue-2703.ts new file mode 100644 index 0000000000..cc6d6f8c4b --- /dev/null +++ b/test/github-issues/2703/issue-2703.ts @@ -0,0 +1,42 @@ +import {expect} from "chai"; +import {Connection} from "../../../src/connection/Connection"; +import {createTestingConnections, reloadTestingDatabases, closeTestingConnections} from "../../utils/test-utils"; +import {Dummy} from "./entity/Dummy"; +import {WrappedString} from "./wrapped-string"; +import {MemoryLogger} from "./memory-logger"; + +describe("github issues > #2703 Column with transformer is not normalized for update", () => { + let connections: Connection[]; + + before(async () => connections = await createTestingConnections({ + entities: [`${__dirname}/entity/*{.js,.ts}`], + schemaCreate: true, + dropSchema: true, + createLogger: () => new MemoryLogger(false), + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + afterEach(() => connections.forEach(connection => { + const logger = connection.logger as MemoryLogger; + logger.enabled = false; + logger.clear(); + })); + + it("should transform values when computing changed columns", () => Promise.all(connections.map(async connection => { + const repository = connection.getRepository(Dummy); + + const dummy = repository.create({ + value: new WrappedString("test"), + }); + await repository.save(dummy); + + const logger = connection.logger as MemoryLogger; + logger.enabled = true; + + await repository.save(dummy); + + const updateQueries = logger.queries.filter(q => q.startsWith("UPDATE")); + + expect(updateQueries).to.be.empty; + }))); +}); diff --git a/test/github-issues/2703/memory-logger.ts b/test/github-issues/2703/memory-logger.ts new file mode 100644 index 0000000000..3ec36711fc --- /dev/null +++ b/test/github-issues/2703/memory-logger.ts @@ -0,0 +1,32 @@ +import {Logger} from "../../../src/logger/Logger"; + +export class MemoryLogger implements Logger { + constructor(public enabled = true) {} + + private _queries: string[] = []; + get queries() { return this._queries; } + + logQuery(query: string) { + if (this.enabled) { + this._queries.push(query); + } + } + + logQueryError(error: string, query: string) {} + + logQuerySlow(time: number, query: string) {} + + logSchemaBuild(message: string) {} + + logMigration(message: string) {} + + log(level: "log" | "info" | "warn", message: any) {} + + writeToConsole() { + this.queries.forEach(q => console.log(`query: ${q}`)); + } + + clear() { + this._queries = []; + } +} diff --git a/test/github-issues/2703/wrapped-string.ts b/test/github-issues/2703/wrapped-string.ts new file mode 100644 index 0000000000..96b91d90cd --- /dev/null +++ b/test/github-issues/2703/wrapped-string.ts @@ -0,0 +1,14 @@ +import {ValueTransformer} from "../../../src/decorator/options/ValueTransformer"; + +export class WrappedString { + constructor(readonly value: string) {} +} + +export const wrappedStringTransformer: ValueTransformer = { + from(value: string): WrappedString { + return new WrappedString(value); + }, + to(value: WrappedString): string { + return value.value; + } +}; diff --git a/test/github-issues/2733/issue-2733.ts b/test/github-issues/2733/issue-2733.ts index 02ff1074bf..bb4c1eb6cb 100644 --- a/test/github-issues/2733/issue-2733.ts +++ b/test/github-issues/2733/issue-2733.ts @@ -12,7 +12,7 @@ describe("github issues > #2733 should correctly handle function calls with uper entities: [__dirname + "/entity/MSSQLDummy{.js,.ts}"], schemaCreate: true, dropSchema: true, - enabledDrivers: ["mssql", "sqljs", "sqlite"], + enabledDrivers: ["mssql", "sqljs", "sqlite", "better-sqlite3"], }); await reloadTestingDatabases(connections); await Promise.all(connections.map(async connection => { diff --git a/test/github-issues/2943/entity/Test.ts b/test/github-issues/2943/entity/Test.ts new file mode 100644 index 0000000000..9055aa93b1 --- /dev/null +++ b/test/github-issues/2943/entity/Test.ts @@ -0,0 +1,22 @@ +import { Column, Entity, PrimaryColumn } from "../../../../src"; + +@Entity() +export class Test { + @PrimaryColumn() + id: number; + + @Column({ type: 'int', unsigned: true}) + uInt: number; + + @Column({ type: 'tinyint', unsigned: true}) + uTinyInt: number; + + @Column({ type: 'smallint', unsigned: true}) + uSmallInt: number; + + @Column({ type: 'mediumint', unsigned: true}) + uMediumInt: number; + + @Column({ type: 'bigint', unsigned: true}) + uBigInt: number; +} diff --git a/test/github-issues/2943/issue-2943.ts b/test/github-issues/2943/issue-2943.ts new file mode 100644 index 0000000000..5fee6e7754 --- /dev/null +++ b/test/github-issues/2943/issue-2943.ts @@ -0,0 +1,29 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import { Connection } from "../../../src"; +import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; +import { Test } from "./entity/Test"; + +describe("github issues > #2943 Inappropriate migration generated", () => { + + let connections: Connection[]; + + before(async () => { + connections = await createTestingConnections({ + enabledDrivers: ['mariadb', 'mysql'], + entities: [Test], + schemaCreate: true, + dropSchema: true + }); + }); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should not create migrations for unsigned numeric types with no specified width", () => + Promise.all(connections.map(async (connection) => { + const sqlInMemory = await connection.driver.createSchemaBuilder().log(); + + expect(sqlInMemory.upQueries).to.eql([]); + expect(sqlInMemory.downQueries).to.eql([]); + }))); +}); diff --git a/test/github-issues/3111/entity/Test.ts b/test/github-issues/3111/entity/Test.ts new file mode 100644 index 0000000000..dfcf3d2277 --- /dev/null +++ b/test/github-issues/3111/entity/Test.ts @@ -0,0 +1,14 @@ +import {Column} from "../../../../src/decorator/columns/Column"; +import {Entity} from "../../../../src/decorator/entity/Entity"; +import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn"; + +export const DEFAULT_VALUE = "default-value"; + +@Entity() +export class Test { + @PrimaryGeneratedColumn() + id: number; + + @Column({default: DEFAULT_VALUE}) + value: string; +} diff --git a/test/github-issues/3111/issue-3111.ts b/test/github-issues/3111/issue-3111.ts new file mode 100644 index 0000000000..614525200f --- /dev/null +++ b/test/github-issues/3111/issue-3111.ts @@ -0,0 +1,30 @@ +import "reflect-metadata"; +import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; +import {Connection} from "../../../src/connection/Connection"; +import {expect} from "chai"; +import {InsertValuesMissingError} from "../../../src/error/InsertValuesMissingError"; +import {Test, DEFAULT_VALUE} from "./entity/Test"; + +describe("github issues > #3111 Inserting with query builder attempts to insert a default row when values is empty array", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + schemaCreate: true, + dropSchema: true, + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should not insert with default values on .values([])", () => Promise.all(connections.map(async connection => { + const repo = connection.getRepository(Test); + await repo.createQueryBuilder().insert().values([]).execute(); + const rowsWithDefaultValue = await repo.find({ where: {value: DEFAULT_VALUE}}); + expect(rowsWithDefaultValue).to.have.lengthOf(0); + }))); + + it("should still error on missing .values()", () => Promise.all(connections.map(async connection => { + const repo = connection.getRepository(Test); + await repo.createQueryBuilder().insert().execute().should.be.rejectedWith(InsertValuesMissingError); + }))); +}); diff --git a/test/github-issues/3118/issue-3118.ts b/test/github-issues/3118/issue-3118.ts index 40bba8e1bb..f990c32b92 100644 --- a/test/github-issues/3118/issue-3118.ts +++ b/test/github-issues/3118/issue-3118.ts @@ -18,6 +18,7 @@ describe("github issues > #3118 shorten alias names (for RDBMS with a limit) whe let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], + enabledDrivers: ["mysql", "postgres", "cockroachdb", "sap", "mariadb", "mssql"] })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/github-issues/3158/issue-3158.ts b/test/github-issues/3158/issue-3158.ts index d074678c76..7f26cc6da9 100644 --- a/test/github-issues/3158/issue-3158.ts +++ b/test/github-issues/3158/issue-3158.ts @@ -8,7 +8,7 @@ it("github issues > #3158 Cannot run sync a second time", async () => { entities: [__dirname + "/entity/*{.js,.ts}"], schemaCreate: true, dropSchema: true, - enabledDrivers: ["mysql", "mariadb", "oracle", "mssql", "sqljs", "sqlite"], + enabledDrivers: ["mysql", "mariadb", "oracle", "mssql", "sqljs", "sqlite", "better-sqlite3"], // todo(AlexMesser): check why tests are failing under postgres driver }); await reloadTestingDatabases(connections); diff --git a/test/github-issues/3416/entity/User.ts b/test/github-issues/3416/entity/User.ts new file mode 100644 index 0000000000..c8e2ff0060 --- /dev/null +++ b/test/github-issues/3416/entity/User.ts @@ -0,0 +1,17 @@ +import {Entity} from "../../../../src/decorator/entity/Entity"; +import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn"; +import {Column} from "../../../../src/decorator/columns/Column"; + +@Entity() +export class User { + + @PrimaryGeneratedColumn() + id: number; + + @Column() + name: string; + + @Column() + likesCount: number = 0; + +} diff --git a/test/github-issues/3416/issue-3416.ts b/test/github-issues/3416/issue-3416.ts new file mode 100644 index 0000000000..c67df820b2 --- /dev/null +++ b/test/github-issues/3416/issue-3416.ts @@ -0,0 +1,47 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; +import { Connection } from "../../../src/connection/Connection"; +import {User} from "../../functional/query-builder/update/entity/User"; +import {EntityColumnNotFound} from "../../../src/error/EntityColumnNotFound"; + +describe("github issues > #3416 Unknown fields are stripped from WHERE clause", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [User] + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + describe("should throw EntityColumnNotFound when supplying unknown property in where criteria", () => { + it("find", () => Promise.all(connections.map(async connection => { + let error: Error | undefined; + try { + // @ts-ignore + await connection.manager.findOne(User, { unknownProp: "John Doe" }); + } catch (err) { + error = err; + } + expect(error).to.be.an.instanceof(EntityColumnNotFound); + }))); + it("update", () => Promise.all(connections.map(async connection => { + let error: Error | undefined; + try { + await connection.manager.update(User, { unknownProp: "Something" } as any, { name: "John doe "}); + } catch (err) { + error = err; + } + expect(error).to.be.an.instanceof(EntityColumnNotFound); + }))); + it("delete", () => Promise.all(connections.map(async connection => { + let error: Error | undefined; + try { + await connection.manager.delete(User, { unknownProp: "Something" } as any); + } catch (err) { + error = err; + } + expect(error).to.be.an.instanceof(EntityColumnNotFound); + }))); + }); +}); diff --git a/test/github-issues/3422/issue-3422.ts b/test/github-issues/3422/issue-3422.ts index 01ebf26034..3687e994f9 100644 --- a/test/github-issues/3422/issue-3422.ts +++ b/test/github-issues/3422/issue-3422.ts @@ -2,7 +2,6 @@ import "reflect-metadata"; import {Connection} from "../../../src/connection/Connection"; import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils"; import {User} from "./entity/User"; -import {PromiseUtils} from "../../../src"; describe("github issues > #3422 cannot save to nested-tree table if schema is used in postgres", () => { @@ -16,7 +15,7 @@ describe("github issues > #3422 cannot save to nested-tree table if schema is us }); after(() => closeTestingConnections(connections)); - it("should not fail when using schema and nested-tree", () => PromiseUtils.runInSequence(connections, async connection => { + it("should not fail when using schema and nested-tree", () => Promise.all(connections.map(async connection => { await connection.query("CREATE SCHEMA IF NOT EXISTS admin"); await connection.synchronize(); const parent = new User(); @@ -28,5 +27,5 @@ describe("github issues > #3422 cannot save to nested-tree table if schema is us const user = await connection.manager.getRepository(User).findOne(child.id, {relations: ["manager"]}); user!.id.should.be.equal(child.id); user!.manager.id.should.be.equal(parent.id); - })); + }))); }); diff --git a/test/github-issues/3496/issue-3496.ts b/test/github-issues/3496/issue-3496.ts index 8bcea0464d..f96eee3f1c 100644 --- a/test/github-issues/3496/issue-3496.ts +++ b/test/github-issues/3496/issue-3496.ts @@ -2,7 +2,6 @@ import "reflect-metadata"; import {Connection} from "../../../src"; import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils"; import {Post} from "./entity/Post"; -import {PromiseUtils} from "../../../src"; describe("github issues > #3496 jsonb comparison doesn't work", () => { @@ -16,7 +15,7 @@ describe("github issues > #3496 jsonb comparison doesn't work", () => { }); after(() => closeTestingConnections(connections)); - it("the entity should not be updated a second time", () => PromiseUtils.runInSequence(connections, async connection => { + it("the entity should not be updated a second time", () => Promise.all(connections.map(async connection => { await connection.synchronize(); const repository = connection.getRepository(Post); @@ -34,5 +33,5 @@ describe("github issues > #3496 jsonb comparison doesn't work", () => { ); savedPost1!.version.should.be.equal(savedPost2!.version); - })); + }))); }); diff --git a/test/github-issues/3534/issue-3534.ts b/test/github-issues/3534/issue-3534.ts index 247bcb3d8f..bcf25c022b 100644 --- a/test/github-issues/3534/issue-3534.ts +++ b/test/github-issues/3534/issue-3534.ts @@ -1,6 +1,6 @@ import "reflect-metadata"; import {expect} from "chai"; -import { Connection, PromiseUtils } from "../../../src"; +import { Connection } from "../../../src"; import { Foo } from "./entity/Foo"; import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; @@ -14,7 +14,7 @@ describe("github issues > #3534: store regexp", () => { beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); - it("allows entities with regexp columns", () => PromiseUtils.runInSequence(connections, async connection => { + it("allows entities with regexp columns", () => Promise.all(connections.map(async connection => { const repository = connection.getRepository(Foo); const foo = new Foo(); @@ -25,6 +25,6 @@ describe("github issues > #3534: store regexp", () => { const storedFoo = await repository.findOneOrFail(foo.id); expect(storedFoo.bar).to.instanceOf(RegExp); expect(storedFoo.bar.toString()).to.eq(/foo/i.toString()); - })); + }))); }); diff --git a/test/github-issues/3536/issue-3536.ts b/test/github-issues/3536/issue-3536.ts index 2a284ddbde..39d454f768 100644 --- a/test/github-issues/3536/issue-3536.ts +++ b/test/github-issues/3536/issue-3536.ts @@ -1,7 +1,6 @@ import "reflect-metadata"; import { Connection } from "../../../src/connection/Connection"; import { closeTestingConnections, createTestingConnections } from "../../utils/test-utils"; -import { PromiseUtils } from "../../../src"; import { Roles } from "./entity/Roles"; describe("github issues > #3536 Sync only works once for enums on entities with capital letters in entity name", () => { @@ -18,8 +17,8 @@ describe("github issues > #3536 Sync only works once for enums on entities with }); after(() => closeTestingConnections(connections)); - it("should run without throw error", () => PromiseUtils.runInSequence(connections, async connection => { + it("should run without throw error", () => Promise.all(connections.map(async connection => { await connection.synchronize(); await connection.synchronize(); - })); + }))); }); diff --git a/test/github-issues/3551/issue-3551.ts b/test/github-issues/3551/issue-3551.ts index 2e89dd812f..8d5bc5bdcc 100644 --- a/test/github-issues/3551/issue-3551.ts +++ b/test/github-issues/3551/issue-3551.ts @@ -1,7 +1,6 @@ import "reflect-metadata"; import {Connection} from "../../../src/connection/Connection"; import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils"; -import {PromiseUtils} from "../../../src"; import { Book } from "./entity/Book"; describe("github issues > #3551 array of embedded documents through multiple levels are not handled", () => { @@ -16,7 +15,7 @@ describe("github issues > #3551 array of embedded documents through multiple lev }); after(() => closeTestingConnections(connections)); - it("should return entity with all these embedded documents", () => PromiseUtils.runInSequence(connections, async connection => { + it("should return entity with all these embedded documents", () => Promise.all(connections.map(async connection => { const bookInput = { title: "Book 1", chapters: [ @@ -59,5 +58,5 @@ describe("github issues > #3551 array of embedded documents through multiple lev book!.chapters[1].pages.should.have.lengthOf(2); book!.chapters[1].pages[0].number.should.be.equal(bookInput.chapters[1].pages[0].number); book!.chapters[1].pages[1].number.should.be.equal(bookInput.chapters[1].pages[1].number); - })); -}); \ No newline at end of file + }))); +}); diff --git a/test/github-issues/3654/entity/User.ts b/test/github-issues/3654/entity/User.ts deleted file mode 100644 index 99a0a9ee7f..0000000000 --- a/test/github-issues/3654/entity/User.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { StringDecoder } from "string_decoder"; -import { Column, Entity, PrimaryColumn } from "../../../../src"; - -@Entity() -export class User { - - @PrimaryColumn("binary", { - length: 16 - }) - public _id: Buffer; - get id(): string { - const decoder = new StringDecoder("hex"); - - return decoder.end(this._id); - } - set id(value: string) { - this._id = Buffer.from(value, "hex"); - } - - @Column() - age: number; - -} diff --git a/test/github-issues/3654/issue-3654.ts b/test/github-issues/3654/issue-3654.ts deleted file mode 100644 index f88b8ff33e..0000000000 --- a/test/github-issues/3654/issue-3654.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Connection } from "../../../src"; -import { - closeTestingConnections, - createTestingConnections, - reloadTestingDatabases -} from "../../utils/test-utils"; -import { User } from "./entity/User"; - -// todo: doesn't work since 0.3.x, fix it later -describe.skip("github issues > #3654 Should be able compare buffer type", () => { - let connections: Connection[]; - before( - async () => - (connections = await createTestingConnections({ - entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["mysql"] - })) - ); - beforeEach(() => reloadTestingDatabases(connections)); - after(() => closeTestingConnections(connections)); - - it("Repository.save() method should be able compare buffer type for deciding if save or update ops.", () => - Promise.all( - connections.map(async connection => { - const userRepo = connection.getRepository(User); - - let userId = "4321226123455910A532153E57A78445".toLowerCase(); - - const user = new User(); - user.id = userId; - user.age = 25; - await userRepo.save(user); - - const dbUser = (await userRepo.find({ - where: { - id: userId - } - }))[0]; - - dbUser.age = 26; - await userRepo.save(dbUser); - - const confirmUser = (await userRepo.find({ - where: { - id: userId - } - }))[0]; - - confirmUser.id.should.be.eql(userId); - confirmUser.age.should.be.eql(26); - }) - )); -}); diff --git a/test/github-issues/3874/entity/Settings.ts b/test/github-issues/3874/entity/Settings.ts new file mode 100644 index 0000000000..2d3cdc0866 --- /dev/null +++ b/test/github-issues/3874/entity/Settings.ts @@ -0,0 +1,16 @@ +import {Entity, Column, PrimaryColumn} from "../../../../src"; + +enum Singleton { + EMPTY = "" +} + +@Entity() +export class Settings { + + @PrimaryColumn() + readonly singleton: Singleton = Singleton.EMPTY; + + @Column() + value!: string; + +} diff --git a/test/github-issues/3874/issue-3874.ts b/test/github-issues/3874/issue-3874.ts new file mode 100644 index 0000000000..4aa095de4f --- /dev/null +++ b/test/github-issues/3874/issue-3874.ts @@ -0,0 +1,30 @@ +import "reflect-metadata"; +import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; +import {Connection} from "../../../src/connection/Connection"; +import {Settings} from "./entity/Settings"; +import {expect} from "chai"; + +describe("github issues > #3874 Using an (empty string) enum as the type of a primary key column", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [Settings], + enabledDrivers: ["mysql", "mariadb"], + schemaCreate: true, + dropSchema: true, + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should reload entity", () => Promise.all(connections.map(async connection => { + // Create initial settings row + const newSettings = new Settings(); + newSettings.value = "string"; + await connection.manager.save(newSettings); + // Attempt to read settings back + const foundSettings = await connection.manager.findOne(Settings); + expect(foundSettings).to.be.an.instanceOf(Settings); + expect(foundSettings != null ? foundSettings.value : null).to.equal("string"); + }))); + +}); diff --git a/test/github-issues/3949/issue-3949.ts b/test/github-issues/3949/issue-3949.ts index 1e89826a45..a2bf94e917 100644 --- a/test/github-issues/3949/issue-3949.ts +++ b/test/github-issues/3949/issue-3949.ts @@ -11,7 +11,7 @@ describe("github issues > #3949 sqlite date hydration is susceptible to corrupti entities: [__dirname + "/entity/*{.js,.ts}"], schemaCreate: true, dropSchema: true, - enabledDrivers: ["sqlite", "sqljs"], + enabledDrivers: ["sqlite", "better-sqlite3", "sqljs"], }); }); beforeEach(() => reloadTestingDatabases(connections)); diff --git a/test/github-issues/4096/issue-4096.ts b/test/github-issues/4096/issue-4096.ts index 3685d0d17a..40f200f209 100644 --- a/test/github-issues/4096/issue-4096.ts +++ b/test/github-issues/4096/issue-4096.ts @@ -9,7 +9,7 @@ describe("github issues > #4096 SQLite support for orUpdate", () => { before(async () => connections = await createTestingConnections({ entities: [User], - enabledDrivers: ["sqlite"], + enabledDrivers: ["sqlite", "better-sqlite3"], schemaCreate: true, dropSchema: true, })); diff --git a/test/github-issues/4147/issue-4147.ts b/test/github-issues/4147/issue-4147.ts index d57a645e72..43b52aa152 100644 --- a/test/github-issues/4147/issue-4147.ts +++ b/test/github-issues/4147/issue-4147.ts @@ -14,7 +14,7 @@ describe("github issues > #4147 `SQLITE_ERROR: near \"-\": syntax error` when us (connections = await createTestingConnections({ entities: [new EntitySchema(PostSchema)], dropSchema: true, - enabledDrivers: ["sqlite"] + enabledDrivers: ["sqlite", "better-sqlite3"] })) ); beforeEach(() => reloadTestingDatabases(connections)); diff --git a/test/github-issues/4156/issue-4156.ts b/test/github-issues/4156/issue-4156.ts index 4bb754f073..ffa4be3095 100644 --- a/test/github-issues/4156/issue-4156.ts +++ b/test/github-issues/4156/issue-4156.ts @@ -1,85 +1,85 @@ -import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; -import { Connection } from "../../../src/connection/Connection"; -import { EntitySchema, In } from "../../../src"; -import { Author, AuthorSchema } from "./entity/Author"; -import { Post, PostSchema } from "./entity/Post"; +import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; +import {Connection} from "../../../src/connection/Connection"; +import {EntitySchema, In} from "../../../src"; +import {Author, AuthorSchema} from "./entity/Author"; +import {Post, PostSchema} from "./entity/Post"; describe("github issues > #4156 QueryExpressionMap doesn't clone all values correctly", () => { - let connections: Connection[]; - before( - async () => - (connections = await createTestingConnections({ - entities: [new EntitySchema(AuthorSchema), new EntitySchema(PostSchema)], - dropSchema: true, - enabledDrivers: ["postgres"], - })) - ); - beforeEach(() => reloadTestingDatabases(connections)); - after(() => closeTestingConnections(connections)); + let connections: Connection[]; + before( + async () => + (connections = await createTestingConnections({ + entities: [new EntitySchema(AuthorSchema), new EntitySchema(PostSchema)], + dropSchema: true, + enabledDrivers: ["postgres"], + })) + ); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); - async function prepareData(connection: Connection) { - const author = new Author(); - author.id = 1; - author.name = "Jane Doe"; - await connection.manager.save(author); + async function prepareData(connection: Connection) { + const author = new Author(); + author.id = 1; + author.name = "Jane Doe"; + await connection.manager.save(author); - const post = new Post(); - post.id = 1; - post.title = "Post 1"; - post.author = author; - await connection.manager.save(post); - } + const post = new Post(); + post.id = 1; + post.title = "Post 1"; + post.author = author; + await connection.manager.save(post); + } - it("should not error when the query builder has been cloned", () => - Promise.all( - connections.map(async connection => { - await prepareData(connection); + it("should not error when the query builder has been cloned", () => + Promise.all( + connections.map(async connection => { + await prepareData(connection); - const qb = connection.manager - .createQueryBuilder("Post", "post") - .disableEagerRelations(); + const qb = connection.manager + .createQueryBuilder("Post", "post") + .disableEagerRelations(); - const [loadedPost1, loadedPost2] = await Promise.all([ - qb.clone().where({ id: 1 }).getOne(), - qb.clone().where({ id: In([1]) }).getOne(), - ]); + const [loadedPost1, loadedPost2] = await Promise.all([ + qb.clone().where({ id: 1 }).getOne(), + qb.clone().where({ id: In([1]) }).getOne(), + ]) as Post[]; - (loadedPost1 as Post).should.be.eql({ - id: 1, - title: "Post 1" - }); + loadedPost1!.should.be.eql({ + id: 1, + title: "Post 1" + }); - (loadedPost2 as Post).should.be.eql({ - id: 1, - title: "Post 1" - }); - }) - )); + loadedPost2!.should.be.eql({ + id: 1, + title: "Post 1" + }); + }) + )); - it("should not error when the query builder with where statement has been cloned", () => - Promise.all( - connections.map(async connection => { - await prepareData(connection); + it("should not error when the query builder with where statement has been cloned", () => + Promise.all( + connections.map(async connection => { + await prepareData(connection); - const qb = connection.manager - .createQueryBuilder("Post", "post") - .disableEagerRelations() - .where({ id: 1 }); + const qb = connection.manager + .createQueryBuilder("Post", "post") + .disableEagerRelations() + .where({ id: 1 }); - const [loadedPost1, loadedPost2] = await Promise.all([ - qb.clone().getOne(), - qb.clone().getOne(), - ]); + const [loadedPost1, loadedPost2] = await Promise.all([ + qb.clone().getOne(), + qb.clone().getOne(), + ]) as Post[]; - (loadedPost1 as Post).should.be.eql({ - id: 1, - title: "Post 1" - }); + loadedPost1!.should.be.eql({ + id: 1, + title: "Post 1" + }); - (loadedPost2 as Post).should.be.eql({ - id: 1, - title: "Post 1" - }); - }) - )); + loadedPost2!.should.be.eql({ + id: 1, + title: "Post 1" + }); + }) + )); }); diff --git a/test/github-issues/4410/entity/Username.ts b/test/github-issues/4410/entity/Username.ts new file mode 100644 index 0000000000..ad0ee27175 --- /dev/null +++ b/test/github-issues/4410/entity/Username.ts @@ -0,0 +1,12 @@ +import { Column } from "../../../../src/decorator/columns/Column"; +import { PrimaryColumn } from "../../../../src/decorator/columns/PrimaryColumn"; +import { Entity } from "../../../../src/decorator/entity/Entity"; + +@Entity() +export class Username { + @PrimaryColumn() + username: string; + + @Column() + email: string; +} diff --git a/test/github-issues/4410/issue-4410.ts b/test/github-issues/4410/issue-4410.ts new file mode 100644 index 0000000000..cf23b9856f --- /dev/null +++ b/test/github-issues/4410/issue-4410.ts @@ -0,0 +1,87 @@ +import appRootPath from "app-root-path"; +import sinon from "sinon"; +import { Connection, FileLogger } from "../../../src"; +import { createTestingConnections, reloadTestingDatabases, closeTestingConnections, TestingOptions } from "../../utils/test-utils"; +import { Username } from "./entity/Username"; +import { PlatformTools } from "../../../src/platform/PlatformTools"; + +describe("github issues > #4410 allow custom filepath for FileLogger", () => { + let connections: Connection[]; + let stub: sinon.SinonStub; + + const testingOptions: TestingOptions = { + entities: [Username], + schemaCreate: true, + dropSchema: true, + }; + + before(() => stub = sinon.stub(PlatformTools, "appendFileSync")); + beforeEach(() => reloadTestingDatabases(connections)); + afterEach(async () => { + stub.resetHistory(); await closeTestingConnections(connections); + }); + + describe("when no option is passed", () => { + before(async () => { + connections = await createTestingConnections({ + ...testingOptions, + createLogger: () => new FileLogger("all"), + }); + }); + it("writes to the base path", async () => + Promise.all(connections.map(async (connection) => { + const testQuery = `SELECT COUNT(*) FROM ${connection.driver.escape('username')}`; + + await connection.query(testQuery); + sinon.assert.calledWith( + stub, + appRootPath.path + "/ormlogs.log", + sinon.match(testQuery) + ); + }))); + }); + + describe("when logPath option is passed as a file", () => { + before(async () => { + connections = await createTestingConnections({ + ...testingOptions, + createLogger: () => new FileLogger("all", { + logPath: "test.log" + }), + }); + }); + it("writes to the given filename", async () => + Promise.all(connections.map(async (connection) => { + const testQuery = `SELECT COUNT(*) FROM ${connection.driver.escape('username')}`; + + await connection.query(testQuery); + sinon.assert.calledWith( + stub, + appRootPath.path + "/test.log", + sinon.match(testQuery) + ); + }))); + }); + + describe("when logPath option is passed as a nested path", () => { + before(async () => { + connections = await createTestingConnections({ + ...testingOptions, + createLogger: () => new FileLogger("all", { + logPath: "./test/test.log" + }), + }); + }); + it("writes to the given path", () => + Promise.all(connections.map(async (connection) => { + const testQuery = `SELECT COUNT(*) FROM ${connection.driver.escape('username')}`; + + await connection.query(testQuery); + sinon.assert.calledWith( + stub, + appRootPath.path + "/test/test.log", + sinon.match(testQuery) + ); + }))); + }); +}); diff --git a/test/github-issues/4415/entity/Post.ts b/test/github-issues/4415/entity/Post.ts new file mode 100644 index 0000000000..94e6f92ea5 --- /dev/null +++ b/test/github-issues/4415/entity/Post.ts @@ -0,0 +1,14 @@ +import { PrimaryGeneratedColumn, Entity, Column, CreateDateColumn } from "../../../../src"; + +@Entity() +export class Post { + + @PrimaryGeneratedColumn() + id?: number; + + @Column() + title: string; + + @CreateDateColumn() + readonly createdAt?: Date; +} diff --git a/test/github-issues/4415/entity/Username.ts b/test/github-issues/4415/entity/Username.ts new file mode 100644 index 0000000000..b1f7b55552 --- /dev/null +++ b/test/github-issues/4415/entity/Username.ts @@ -0,0 +1,15 @@ +import { Column } from "../../../../src/decorator/columns/Column"; +import { PrimaryColumn } from "../../../../src/decorator/columns/PrimaryColumn"; +import { Entity } from "../../../../src/decorator/entity/Entity"; + +@Entity() +export class Username { + @PrimaryColumn() + username: string; + + @Column() + email: string; + + @Column() + something: string; +} diff --git a/test/github-issues/4415/issue-4415.ts b/test/github-issues/4415/issue-4415.ts new file mode 100644 index 0000000000..5f0a08af57 --- /dev/null +++ b/test/github-issues/4415/issue-4415.ts @@ -0,0 +1,108 @@ +import sinon from "sinon"; +import { ConnectionOptions, ConnectionOptionsReader, DatabaseType } from "../../../src"; +import { setupTestingConnections, createTestingConnections, closeTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; +import { Username } from "./entity/Username"; +import { CommandUtils } from "../../../src/commands/CommandUtils"; +import { MigrationGenerateCommand } from "../../../src/commands/MigrationGenerateCommand"; +import { Post } from "./entity/Post"; +import { resultsTemplates } from "./results-templates"; + +describe("github issues > #4415 allow beautify generated migrations", () => { + let connectionOptions: ConnectionOptions[]; + let createFileStub: sinon.SinonStub; + let getConnectionOptionsStub: sinon.SinonStub; + let migrationGenerateCommand: MigrationGenerateCommand; + let connectionOptionsReader: ConnectionOptionsReader; + let baseConnectionOptions: ConnectionOptions; + + const enabledDrivers = [ + "postgres", + "mssql", + "mysql", + "mariadb", + "sqlite", + "better-sqlite3", + "oracle", + "cockroachdb" + ] as DatabaseType[]; + + // simulate args: `npm run typeorm migration:run -- -n test-migration -d test-directory` + const testHandlerArgs = (options: Record) => ({ + "$0": "test", + "_": ["test"], + "name": "test-migration", + "dir": "test-directory", + ...options + }); + + before(async () => { + // clean out db from any prior tests in case previous state impacts the generated migrations + const connections = await createTestingConnections({ + entities: [], + enabledDrivers + }); + await reloadTestingDatabases(connections); + await closeTestingConnections(connections); + + connectionOptions = await setupTestingConnections({ + entities: [Username, Post], + enabledDrivers + }); + connectionOptionsReader = new ConnectionOptionsReader(); + migrationGenerateCommand = new MigrationGenerateCommand(); + createFileStub = sinon.stub(CommandUtils, "createFile"); + }); + after(() => createFileStub.restore()); + + it("writes regular migration file when no option is passed", async () => { + for (const connectionOption of connectionOptions) { + createFileStub.resetHistory(); + baseConnectionOptions = await connectionOptionsReader.get(connectionOption.name as string); + getConnectionOptionsStub = sinon.stub(ConnectionOptionsReader.prototype, "get").resolves({ + ...baseConnectionOptions, + entities: [Username, Post] + }); + + await migrationGenerateCommand.handler(testHandlerArgs({ + "connection": connectionOption.name + })); + + // compare against control test strings in results-templates.ts + for (const control of resultsTemplates[connectionOption.type as string].control) { + sinon.assert.calledWith( + createFileStub, + sinon.match(/test-directory.*test-migration.ts/), + sinon.match(control) + ); + } + + getConnectionOptionsStub.restore(); + } + }); + + it("writes pretty printed file when pretty option is passed", async () => { + for (const connectionOption of connectionOptions) { + createFileStub.resetHistory(); + baseConnectionOptions = await connectionOptionsReader.get(connectionOption.name as string); + getConnectionOptionsStub = sinon.stub(ConnectionOptionsReader.prototype, "get").resolves({ + ...baseConnectionOptions, + entities: [Username, Post] + }); + + await migrationGenerateCommand.handler(testHandlerArgs({ + "connection": connectionOption.name, + "pretty": true + })); + + // compare against "pretty" test strings in results-templates.ts + for (const pretty of resultsTemplates[connectionOption.type as string].pretty) { + sinon.assert.calledWith( + createFileStub, + sinon.match(/test-directory.*test-migration.ts/), + sinon.match(pretty) + ); + } + getConnectionOptionsStub.restore(); + } + }); +}); diff --git a/test/github-issues/4415/results-templates.ts b/test/github-issues/4415/results-templates.ts new file mode 100644 index 0000000000..1cd7d18a05 --- /dev/null +++ b/test/github-issues/4415/results-templates.ts @@ -0,0 +1,157 @@ +export const resultsTemplates: Record = { + + postgres: { + control: [ + `CREATE TABLE "post" ("id" SERIAL NOT NULL, "title" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id"))`, + `CREATE TABLE "username" ("username" character varying NOT NULL, "email" character varying NOT NULL, "something" character varying NOT NULL, CONSTRAINT "PK_b39ad32e514b17e90c93988888a" PRIMARY KEY ("username"))` + ], + pretty: [ + ` + CREATE TABLE "post" ( + "id" SERIAL NOT NULL, + "title" character varying NOT NULL, + "createdAt" TIMESTAMP NOT NULL DEFAULT now(), + CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id") + ) + `, + ` + CREATE TABLE "username" ( + "username" character varying NOT NULL, + "email" character varying NOT NULL, + "something" character varying NOT NULL, + CONSTRAINT "PK_b39ad32e514b17e90c93988888a" PRIMARY KEY ("username") + ) + ` + ] + }, + + mssql: { + control: [ + `CREATE TABLE "post" ("id" int NOT NULL IDENTITY(1,1), "title" nvarchar(255) NOT NULL, "createdAt" datetime2 NOT NULL CONSTRAINT "DF_fb91bea2d37140a877b775e6b2a" DEFAULT getdate(), CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id"))`, + `CREATE TABLE "username" ("username" nvarchar(255) NOT NULL, "email" nvarchar(255) NOT NULL, "something" nvarchar(255) NOT NULL, CONSTRAINT "PK_b39ad32e514b17e90c93988888a" PRIMARY KEY ("username"))` + ], + pretty: [ + ` + CREATE TABLE "post" ( + "id" int NOT NULL IDENTITY(1, 1), + "title" nvarchar(255) NOT NULL, + "createdAt" datetime2 NOT NULL CONSTRAINT "DF_fb91bea2d37140a877b775e6b2a" DEFAULT getdate(), + CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id") + ) + `, + ` + CREATE TABLE "username" ( + "username" nvarchar(255) NOT NULL, + "email" nvarchar(255) NOT NULL, + "something" nvarchar(255) NOT NULL, + CONSTRAINT "PK_b39ad32e514b17e90c93988888a" PRIMARY KEY ("username") + ) + ` + ] + }, + + sqlite: { + control: [ + `CREATE TABLE "post" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "title" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')))`, + `CREATE TABLE "username" ("username" varchar PRIMARY KEY NOT NULL, "email" varchar NOT NULL, "something" varchar NOT NULL)`, + ], + pretty: [ + ` + CREATE TABLE "post" ( + "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, + "title" varchar NOT NULL, + "createdAt" datetime NOT NULL DEFAULT (datetime('now')) + ) + `, + ` + CREATE TABLE "username" ( + "username" varchar PRIMARY KEY NOT NULL, + "email" varchar NOT NULL, + "something" varchar NOT NULL + ) + ` + ] + }, + + mysql: { + control: [ + `CREATE TABLE \`post\` (\`id\` int NOT NULL AUTO_INCREMENT, \`title\` varchar(255) NOT NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + `CREATE TABLE \`username\` (\`username\` varchar(255) NOT NULL, \`email\` varchar(255) NOT NULL, \`something\` varchar(255) NOT NULL, PRIMARY KEY (\`username\`)) ENGINE=InnoDB` + ], + pretty: [ + ` + CREATE TABLE \`post\` ( + \`id\` int NOT NULL AUTO_INCREMENT, + \`title\` varchar(255) NOT NULL, + \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), + PRIMARY KEY (\`id\`) + ) ENGINE = InnoDB + `, + ` + CREATE TABLE \`username\` ( + \`username\` varchar(255) NOT NULL, + \`email\` varchar(255) NOT NULL, + \`something\` varchar(255) NOT NULL, + PRIMARY KEY (\`username\`) + ) ENGINE = InnoDB + ` + ] + }, + + oracle: { + control: [ + `CREATE TABLE "post" ("id" number GENERATED BY DEFAULT AS IDENTITY, "title" varchar2(255) NOT NULL, "createdAt" timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL, CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id"))`, + `CREATE TABLE "username" ("username" varchar2(255) NOT NULL, "email" varchar2(255) NOT NULL, "something" varchar2(255) NOT NULL, CONSTRAINT "PK_b39ad32e514b17e90c93988888a" PRIMARY KEY ("username"))` + ], + pretty: [ + ` + CREATE TABLE "post" ( + "id" number GENERATED BY DEFAULT AS IDENTITY, + "title" varchar2(255) NOT NULL, + "createdAt" timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL, + CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id") + ) + `, + ` + CREATE TABLE "username" ( + "username" varchar2(255) NOT NULL, + "email" varchar2(255) NOT NULL, + "something" varchar2(255) NOT NULL, + CONSTRAINT "PK_b39ad32e514b17e90c93988888a" PRIMARY KEY ("username") + ) + ` + ] + }, + + cockroachdb: { + control: [ + `CREATE SEQUENCE "post_id_seq"`, + `CREATE TABLE "post" ("id" INT4 DEFAULT nextval('"post_id_seq"') NOT NULL, "title" varchar NOT NULL, "createdAt" timestamptz NOT NULL DEFAULT now(), CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id"))`, + `CREATE TABLE "username" ("username" varchar NOT NULL, "email" varchar NOT NULL, "something" varchar NOT NULL, CONSTRAINT "PK_b39ad32e514b17e90c93988888a" PRIMARY KEY ("username"))` + ], + pretty: [ + ` + CREATE SEQUENCE "post_id_seq" + `, + ` + CREATE TABLE "post" ( + "id" INT4 DEFAULT nextval('"post_id_seq"') NOT NULL, + "title" varchar NOT NULL, + "createdAt" timestamptz NOT NULL DEFAULT now(), + CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id") + ) + `, + ` + CREATE TABLE "username" ( + "username" varchar NOT NULL, + "email" varchar NOT NULL, + "something" varchar NOT NULL, + CONSTRAINT "PK_b39ad32e514b17e90c93988888a" PRIMARY KEY ("username") + ) + ` + ] + }, + + get mariadb() { return this.mysql; }, + get "better-sqlite3"() { return this.sqlite; }, +}; diff --git a/test/github-issues/4878/issue-4878.ts b/test/github-issues/4878/issue-4878.ts new file mode 100644 index 0000000000..8359d8b0ed --- /dev/null +++ b/test/github-issues/4878/issue-4878.ts @@ -0,0 +1,19 @@ +import { DriverUtils } from "../../../src/driver/DriverUtils"; +import { expect } from "chai"; + +describe("github issues > #4878 URL Connection string not overridden by supplied options", () => { + it("should override url-built options with user-supplied options", () => { + const obj: any = { + username: "user", + password: "password", + host: "host", + database: "database", + port: 8888 + }; + + const url = `postgres://url_user:${obj.password}@${obj.host}:${obj.port}/${obj.database}`; + obj.url = url; + const options = DriverUtils.buildDriverOptions(obj); + expect(options.username).to.eql(obj.username); + }); +}); diff --git a/test/github-issues/5067/issue-5067.ts b/test/github-issues/5067/issue-5067.ts new file mode 100644 index 0000000000..3082a03894 --- /dev/null +++ b/test/github-issues/5067/issue-5067.ts @@ -0,0 +1,20 @@ +import "reflect-metadata"; +import {expect} from "chai"; +import {Connection} from "../../../src"; +import {closeTestingConnections, createTestingConnections} from "../../utils/test-utils"; + +describe("github issues > #5067 ORA-00972: identifier is too long", () => { + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + enabledDrivers: ["oracle"] + })); + after(() => closeTestingConnections(connections)); + + it("generated parameter name is within the size constraints", () => Promise.all(connections.map(async connection => { + const paramName = "output_that_is_really_long_and_must_be_truncated_in_this_driver"; + const createdParameter = await connection.driver.createParameter(paramName, 0); + + expect(createdParameter).to.be.an("String"); + expect(createdParameter.length).to.be.lessThan(30); + }))); +}); diff --git a/test/github-issues/513/issue-513.ts b/test/github-issues/513/issue-513.ts index be0cf0b754..5d039ca808 100644 --- a/test/github-issues/513/issue-513.ts +++ b/test/github-issues/513/issue-513.ts @@ -11,7 +11,7 @@ describe("github issues > #513 Incorrect time/datetime types for SQLite", () => let connections: Connection[]; before(async () => connections = await createTestingConnections({ entities: [__dirname + "/entity/*{.js,.ts}"], - enabledDrivers: ["sqlite"] + enabledDrivers: ["sqlite", "better-sqlite3"] })); beforeEach(() => reloadTestingDatabases(connections)); after(() => closeTestingConnections(connections)); diff --git a/test/github-issues/5444/entity/Author.ts b/test/github-issues/5444/entity/Author.ts new file mode 100644 index 0000000000..20191b21c5 --- /dev/null +++ b/test/github-issues/5444/entity/Author.ts @@ -0,0 +1,41 @@ +import {EntitySchemaOptions} from "../../../../src/entity-schema/EntitySchemaOptions"; +import {Post} from "./Post"; + +export class Author { + id: number; + + publisherId: number; + + name: string; + + posts: Post[]; +} + +export const AuthorSchema: EntitySchemaOptions = { + name: "Author", + + target: Author, + + columns: { + id: { + primary: true, + type: Number + }, + + publisherId: { + primary: true, + type: Number + }, + + name: { + type: "varchar" + } + }, + + relations: { + posts: { + target: () => Post, + type: "one-to-many" + } + } +}; diff --git a/test/github-issues/5444/entity/Post.ts b/test/github-issues/5444/entity/Post.ts new file mode 100644 index 0000000000..eb5239960c --- /dev/null +++ b/test/github-issues/5444/entity/Post.ts @@ -0,0 +1,53 @@ +import {EntitySchemaOptions} from "../../../../src/entity-schema/EntitySchemaOptions"; +import {Author} from "./Author"; + +export class Post { + authorPublisherId: number; + + authorId: number; + + id: number; + + title: string; + + author: Author; +} + +export const PostSchema: EntitySchemaOptions = { + name: "Post", + + target: Post, + + columns: { + authorPublisherId: { + primary: true, + type: Number + }, + + authorId: { + primary: true, + type: Number + }, + + id: { + primary: true, + type: Number + }, + + title: { + type: "varchar" + } + }, + + relations: { + author: { + target: () => Author, + type: "many-to-one", + eager: true, + joinColumn: [ + { name: "authorPublisherId", referencedColumnName: "publisherId" }, + { name: "authorId", referencedColumnName: "id" }, + ] + } + } +}; diff --git a/test/github-issues/5444/issue-5444.ts b/test/github-issues/5444/issue-5444.ts new file mode 100644 index 0000000000..48d28e797e --- /dev/null +++ b/test/github-issues/5444/issue-5444.ts @@ -0,0 +1,55 @@ +import { EntitySchemaTransformer } from "../../../src/entity-schema/EntitySchemaTransformer"; + +import {expect} from "chai"; + +import { Post, PostSchema } from "./entity/Post"; +import { Author, AuthorSchema } from "./entity/Author"; +import {Connection, EntitySchema} from "../../../src"; +import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils.js"; + + +describe("github issues > #5444 EntitySchema missing support for multiple joinColumns in relations", () => { + let connections: Connection[]; + + before(async () => { + return connections = await createTestingConnections({ + entities: [Post, Author], + schemaCreate: true, + dropSchema: true, + enabledDrivers: ["sqlite"] + }); + }); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("Update query returns the number of affected rows", async () => Promise.all(connections.map(async (connection) => { + const transformer = new EntitySchemaTransformer(); + + const actual = transformer.transform( + connection, + [ + new EntitySchema(AuthorSchema), + new EntitySchema(PostSchema) + ] + ); + + const joinColumns = actual.joinColumns; + + expect(joinColumns.length).to.eq(2); + expect(joinColumns).to.deep.eq([ + { + target: Post, + propertyName: "author", + name: "authorPublisherId", + referencedColumnName: "publisherId" + }, + { + target: Post, + propertyName: "author", + name: "authorId", + referencedColumnName: "id" + }, + + ]); + }))); +}); diff --git a/test/github-issues/57/issue-57.ts b/test/github-issues/57/issue-57.ts index 2c45cca8b9..5b1489c779 100644 --- a/test/github-issues/57/issue-57.ts +++ b/test/github-issues/57/issue-57.ts @@ -1,6 +1,6 @@ import "reflect-metadata"; import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; -import {Connection} from "../../../src"; +import {Connection} from "../../../src/connection/Connection"; import {User} from "./entity/User"; import {expect} from "chai"; import {AccessToken} from "./entity/AccessToken"; diff --git a/test/github-issues/5734/entity/Post.ts b/test/github-issues/5734/entity/Post.ts new file mode 100644 index 0000000000..9d0337791a --- /dev/null +++ b/test/github-issues/5734/entity/Post.ts @@ -0,0 +1,12 @@ +import {PrimaryColumn} from "../../../../src/decorator/columns/PrimaryColumn"; +import {Entity} from "../../../../src/decorator/entity/Entity"; + +@Entity() +export class Post { + @PrimaryColumn() + id: number; + + constructor(id: number) { + this.id = id; + } +} diff --git a/test/github-issues/5734/issue-5734.ts b/test/github-issues/5734/issue-5734.ts new file mode 100644 index 0000000000..1b0cfcf79c --- /dev/null +++ b/test/github-issues/5734/issue-5734.ts @@ -0,0 +1,28 @@ +import "reflect-metadata"; +import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; +import {Connection} from "../../../src/connection/Connection"; +import {Post} from "./entity/Post"; + +describe("github issues > #5734 insert([]) should not crash", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + subscribers: [__dirname + "/subscriber/*{.js,.ts}"], + schemaCreate: true, + dropSchema: true + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should not crash on insert([])", () => Promise.all(connections.map(async connection => { + const repository = connection.getRepository(Post); + await repository.insert([]); + }))); + + it("should still work with a nonempty array", () => Promise.all(connections.map(async connection => { + const repository = connection.getRepository(Post); + await repository.insert([new Post(1)]); + await repository.findOneOrFail({where: {id: 1}}); + }))); +}); diff --git a/test/github-issues/5734/subscriber/CheckValidEntitySubscriber.ts b/test/github-issues/5734/subscriber/CheckValidEntitySubscriber.ts new file mode 100644 index 0000000000..a2573c9236 --- /dev/null +++ b/test/github-issues/5734/subscriber/CheckValidEntitySubscriber.ts @@ -0,0 +1,22 @@ +import {Post} from "../entity/Post"; +import {EntitySubscriberInterface, EventSubscriber, InsertEvent} from "../../../../src"; + +/** + * Subscriber which checks the validity of the entity passed to beforeInsert(). + * Tests the fix for issue #5734 in which we saw an empty array leak into + * beforeInsert(). + */ +@EventSubscriber() +export class ValidEntityCheckSubscriber + implements EntitySubscriberInterface { + listenTo() { + return Post; + } + + beforeInsert(event: InsertEvent) { + const entity = event.entity; + if (Array.isArray(entity) || !entity.id) { + throw new Error(`Subscriber saw invalid entity: ${JSON.stringify(entity)}`); + } + } +} diff --git a/test/github-issues/6066/entity/Session.ts b/test/github-issues/6066/entity/Session.ts new file mode 100644 index 0000000000..f75479a28f --- /dev/null +++ b/test/github-issues/6066/entity/Session.ts @@ -0,0 +1,11 @@ +import {Entity, PrimaryColumn} from "../../../../src"; + +@Entity() +export class Session { + + @PrimaryColumn({ + comment: "That's the way the cookie crumbles" + }) + cookie: string = ""; + +} diff --git a/test/github-issues/6066/issue-6066.ts b/test/github-issues/6066/issue-6066.ts new file mode 100644 index 0000000000..e855499c1b --- /dev/null +++ b/test/github-issues/6066/issue-6066.ts @@ -0,0 +1,22 @@ +import "reflect-metadata"; +import {createTestingConnections, closeTestingConnections} from "../../utils/test-utils"; +import {QueryFailedError, Connection} from "../../../src"; +import {Session} from "./entity/Session"; +import {expect} from "chai"; + +describe("github issues > #6066 Column comment string is not escaped during synchronization", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [Session], + enabledDrivers: ["mysql", "mariadb"], + schemaCreate: false, + dropSchema: true, + })); + after(() => closeTestingConnections(connections)); + + it("should synchronize", () => Promise.all(connections.map(connection => { + return expect(connection.synchronize()).to.not.be.rejectedWith(QueryFailedError); + }))); + +}); diff --git a/test/github-issues/6266/entity/Post.ts b/test/github-issues/6266/entity/Post.ts new file mode 100644 index 0000000000..94e6f92ea5 --- /dev/null +++ b/test/github-issues/6266/entity/Post.ts @@ -0,0 +1,14 @@ +import { PrimaryGeneratedColumn, Entity, Column, CreateDateColumn } from "../../../../src"; + +@Entity() +export class Post { + + @PrimaryGeneratedColumn() + id?: number; + + @Column() + title: string; + + @CreateDateColumn() + readonly createdAt?: Date; +} diff --git a/test/github-issues/6266/issue-6266.ts b/test/github-issues/6266/issue-6266.ts new file mode 100644 index 0000000000..8e8a79e9c0 --- /dev/null +++ b/test/github-issues/6266/issue-6266.ts @@ -0,0 +1,60 @@ +import "reflect-metadata"; +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases, +} from "../../utils/test-utils"; +import { Connection } from "../../../src/connection/Connection"; +import { Post } from "./entity/Post"; +import sinon from "sinon"; +import { SelectQueryBuilder } from "../../../src"; +import { assert } from "chai"; + +describe("github issues > #6266 Many identical selects after insert bunch of items", () => { + let connections: Connection[]; + const posts: Post[] = [ + { + title: "Post 1", + }, + { + title: "Post 2", + }, + { + title: "Post 3", + }, + { + title: "Post 4", + }, + ]; + + before( + async () => + (connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + enabledDrivers: ["mysql"], + })) + ); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should execute a single SELECT to get inserted default and generated values of multiple entities", () => + Promise.all( + connections.map(async (connection) => { + const selectSpy = sinon.spy( + SelectQueryBuilder.prototype, + "select" + ); + + await connection + .createQueryBuilder() + .insert() + .into(Post) + .values(posts) + .execute(); + + assert.strictEqual(selectSpy.calledOnce, true); + + selectSpy.restore(); + }) + )); +}); diff --git a/test/github-issues/6284/issue-6284.ts b/test/github-issues/6284/issue-6284.ts new file mode 100644 index 0000000000..ff686e3cd9 --- /dev/null +++ b/test/github-issues/6284/issue-6284.ts @@ -0,0 +1,36 @@ +import {expect} from "chai"; +import { writeFileSync, unlinkSync } from "fs"; +import { ConnectionOptionsReader } from "../../../src/connection/ConnectionOptionsReader"; +import { importClassesFromDirectories } from "../../../src/util/DirectoryExportedClassesLoader"; +import { LoggerFactory } from "../../../src/logger/LoggerFactory"; + +describe("cli support for cjs extension", () => { + it("will load a cjs file", async () => { + const cjsConfigPath = [__dirname, "ormconfig.cjs"].join("/"); + const databaseType = "postgres"; + const config = `module.exports = {"type": "${databaseType}"};`; + + writeFileSync(cjsConfigPath, config); + const reader = new ConnectionOptionsReader({root: __dirname }); + + const results = await reader.all(); + expect(results).to.be.an("Array"); + expect(results[0]).to.be.an("Object"); + expect(results[0].type).to.equal(databaseType); + + + unlinkSync(cjsConfigPath); + }); + + it("loads cjs files via DirectoryExportedClassesloader", () => { + const klassPath = [__dirname, "klass.cjs"].join("/"); + const klass = `module.exports.Widget = class Widget {};`; + writeFileSync(klassPath, klass); + + const classes = importClassesFromDirectories(new LoggerFactory().create(), [`${__dirname}/*.cjs`]); + expect(classes).to.be.an("Array"); + expect(classes.length).to.eq(1); + + unlinkSync(klassPath); + }); +}); diff --git a/test/github-issues/6389/issue-6389.ts b/test/github-issues/6389/issue-6389.ts new file mode 100644 index 0000000000..a12e9adab1 --- /dev/null +++ b/test/github-issues/6389/issue-6389.ts @@ -0,0 +1,26 @@ +import { DriverUtils } from "../../../src/driver/DriverUtils"; +import { expect } from "chai"; + +describe("github issues > #6389 MongoDB URI Connection string with query params", () => { + it("should parse correctly mongodb URI", () => { + const obj: any = { + type: "mongodb", + username: "user", + password: "password", + host: "host", + database: "database", + port: 27017, + }; + + const url = `${obj.type}://${obj.username}:${obj.password}@${obj.host}:${obj.port}/${obj.database}?readPreference=primary`; + const options = DriverUtils.buildDriverOptions({url}); + + expect(options.type).to.eql(obj.type); + expect(options.username).to.eql(obj.username); + expect(options.username).to.eql(obj.username); + expect(options.password).to.eql(obj.password); + expect(options.host).to.eql(obj.host); + expect(options.port).to.eql(obj.port); + expect(options.database).to.eql(obj.database); + }); +}); diff --git a/test/github-issues/6399/entities.ts b/test/github-issues/6399/entities.ts new file mode 100644 index 0000000000..c3d88f0b85 --- /dev/null +++ b/test/github-issues/6399/entities.ts @@ -0,0 +1,54 @@ +import {Entity, OneToMany, ManyToOne} from "../../../src"; +import {Column} from "../../../src"; +import {PrimaryGeneratedColumn} from "../../../src"; +import { TableInheritance } from "../../../src"; +import {ChildEntity} from "../../../src"; +import {JoinColumn} from "../../../src"; + +@Entity() +@TableInheritance({column: {type: "string", name: "postType"}}) +export class Post { + @PrimaryGeneratedColumn() + id: number; + + @Column() + title: string; + + @Column() + postType: string = "BasePost"; + + @OneToMany(() => Comment, (entity) => entity.post) + comments?: Comment[]; +} + +@ChildEntity("TargetPost") +export class TargetPost extends Post { + @Column() + postType: string = "TargetPost"; +} + + +@Entity() +export class Comment { + @PrimaryGeneratedColumn() + id: number; + + @Column() + text: string; + + @Column() + postId: number; + + @ManyToOne( + () => Post, + (entity) => entity.comments, + ) + @JoinColumn({ + name: "postId", + }) + post?: Post; + +} + + + diff --git a/test/github-issues/6399/issue-6399.ts b/test/github-issues/6399/issue-6399.ts new file mode 100644 index 0000000000..a4f8f2d1b4 --- /dev/null +++ b/test/github-issues/6399/issue-6399.ts @@ -0,0 +1,49 @@ +import {Connection} from "../../../src"; +import {expect} from "chai"; +import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; +import {Post, TargetPost, Comment} from "./entities"; + +describe("github issues > #6399 Process extraAppendedAndWhereCondition for inherited entity", () => { + let connections: Connection[]; + + before(async () => { + return connections = await createTestingConnections({ + entities: [Post, TargetPost, Comment], + schemaCreate: true, + dropSchema: true, + enabledDrivers: ["mysql"] + }); + }); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("Query with join and limit for inhered entity", () => Promise.all(connections.map(async (connection) => { + const targetPostRepo = connection.getRepository(TargetPost); + + const posts: TargetPost[] = [ + { + id: 1, + title: "Post 1", + postType: "TargetPost", + }, + { id: 2, + title: "Post 2", + postType: "TargetPost", + }, + { + id: 3, + title: "Post 3", + postType: "TargetPost", + }, + ]; + + await targetPostRepo.save(posts); + + const result = await targetPostRepo.createQueryBuilder("targetPosts") + .leftJoinAndSelect("targetPosts.comments", "comments") + .take(2) + .getMany(); + + expect(result.length).eq(2); + }))); +}); diff --git a/test/github-issues/6580/entity/Comment.ts b/test/github-issues/6580/entity/Comment.ts new file mode 100644 index 0000000000..1ef8a1139b --- /dev/null +++ b/test/github-issues/6580/entity/Comment.ts @@ -0,0 +1,4 @@ +export class Comment { + any: any; + object: {[k: string]: any}; +} diff --git a/test/github-issues/6580/issue-6580.ts b/test/github-issues/6580/issue-6580.ts new file mode 100644 index 0000000000..d309ad411e --- /dev/null +++ b/test/github-issues/6580/issue-6580.ts @@ -0,0 +1,24 @@ +import {DeepPartial} from "../../../src"; +import {Comment} from "./entity/Comment"; + +describe("github issues > #6580 DeepPartial does not handle `any` and `{[k: string]}`", () => { + + function attemptDeepPartial(entityLike: DeepPartial): void { + } + + it("DeepPartial should correctly handle any", () => { + attemptDeepPartial({ + any: { + foo: 'bar', + } + }) + }); + + it("DeepPartial should correctly handle {[k: string]: any}", () => { + attemptDeepPartial({ + object: { + foo: 'bar' + }, + }) + }); +}); diff --git a/test/github-issues/6633/entity/Test.ts b/test/github-issues/6633/entity/Test.ts new file mode 100644 index 0000000000..61443c6dcd --- /dev/null +++ b/test/github-issues/6633/entity/Test.ts @@ -0,0 +1,11 @@ +import { Entity, PrimaryColumn, Index, Column } from "../../../../src"; + +@Entity() +export class Test { + @PrimaryColumn() + id: number; + + @Index("description_index", { fulltext: true }) + @Column() + description: string; +} diff --git a/test/github-issues/6633/issue-6633.ts b/test/github-issues/6633/issue-6633.ts new file mode 100644 index 0000000000..31df86b5b8 --- /dev/null +++ b/test/github-issues/6633/issue-6633.ts @@ -0,0 +1,29 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import { Connection } from "../../../src"; +import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; +import { Post } from "../4440/entity/Post"; + +describe("github issues > #6633 Fulltext indices continually dropped & re-created", () => { + + let connections: Connection[]; + before(async () => { + connections = await createTestingConnections({ + entities: [Post], + schemaCreate: true, + dropSchema: true + }); + }); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should not create migrations for fulltext indices", () => + Promise.all(connections.map(async (connection) => { + const sqlInMemory = await connection.driver.createSchemaBuilder().log(); + + expect(sqlInMemory.upQueries).to.eql([]); + expect(sqlInMemory.downQueries).to.eql([]); + } + )) + ); +}); diff --git a/test/github-issues/6636/entity/Test.ts b/test/github-issues/6636/entity/Test.ts new file mode 100644 index 0000000000..086363bbbc --- /dev/null +++ b/test/github-issues/6636/entity/Test.ts @@ -0,0 +1,15 @@ +import { Column, Entity, PrimaryColumn } from "../../../../src"; + +@Entity() +export class Test { + + @PrimaryColumn() + id: number; + + @Column({ nullable: true, precision: 6 }) + startedAt?: Date; + + @Column({ type: 'decimal', precision: 5, scale: 2 }) + value: number; + +} diff --git a/test/github-issues/6636/issue-6636.ts b/test/github-issues/6636/issue-6636.ts new file mode 100644 index 0000000000..841f7c4a5a --- /dev/null +++ b/test/github-issues/6636/issue-6636.ts @@ -0,0 +1,25 @@ +import { Connection } from "../../../src"; +import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../utils/test-utils"; +import { Test } from "./entity/Test"; +import { expect } from "chai"; + +describe("github issues > #6636 migration issues with scale & precision", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [Test], + enabledDrivers: ["sqljs", "sqlite", "better-sqlite3"], + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("should not create migrations columns with precision", async () => { + await Promise.all(connections.map(async (connection) => { + const sqlInMemory = await connection.driver.createSchemaBuilder().log(); + expect(sqlInMemory.upQueries).to.eql([]); + expect(sqlInMemory.downQueries).to.eql([]); + } + )) + }); + +}); diff --git a/test/github-issues/6642/entity/v1/entities.ts b/test/github-issues/6642/entity/v1/entities.ts new file mode 100644 index 0000000000..f8df17ccd2 --- /dev/null +++ b/test/github-issues/6642/entity/v1/entities.ts @@ -0,0 +1,18 @@ +import { PrimaryColumn, Generated, Column, Entity } from "../../../../../src"; + +@Entity() +export class FooEntity { + @PrimaryColumn({ type: "int", width: 10, unsigned: true, nullable: false }) + @Generated() + public id: number; +} + +@Entity() +export class BarEntity { + @PrimaryColumn({ type: "int", width: 10, unsigned: true }) + @Generated() + public id: number; + + @Column("varchar", { nullable: false, length: 50 }) + public code: string; +} diff --git a/test/github-issues/6642/entity/v2/entities.ts b/test/github-issues/6642/entity/v2/entities.ts new file mode 100644 index 0000000000..fcf2d1a14b --- /dev/null +++ b/test/github-issues/6642/entity/v2/entities.ts @@ -0,0 +1,34 @@ +import { PrimaryColumn, Generated, ManyToMany, Entity, Column, JoinTable } from "../../../../../src"; + +@Entity() +export class FooEntity { + @PrimaryColumn({ type: "int", width: 10, unsigned: true, nullable: false }) + @Generated() + public id: number; + + @ManyToMany(() => BarEntity) + @JoinTable({ + name: "foo_bars", + joinColumns: [ + { + name: "foo_id", + } + ], + inverseJoinColumns: [ + { + name: "bar_id", + } + ] + }) + public fooBars: BarEntity[]; +} + +@Entity() +export class BarEntity { + @PrimaryColumn({ type: "int", width: 10, unsigned: true }) + @Generated() + public id: number; + + @Column("varchar", { nullable: false, length: 50 }) + public code: string; +} diff --git a/test/github-issues/6642/issue-6642.ts b/test/github-issues/6642/issue-6642.ts new file mode 100644 index 0000000000..b8ba4f7d05 --- /dev/null +++ b/test/github-issues/6642/issue-6642.ts @@ -0,0 +1,67 @@ +import "reflect-metadata"; +import { + closeTestingConnections, + createTestingConnections, + reloadTestingDatabases, + setupSingleTestingConnection +} from "../../utils/test-utils"; +import { Connection, createConnection } from "../../../src"; +import { fail } from "assert"; +import { Query } from "../../../src/driver/Query"; +import { MysqlConnectionOptions } from "../../../src/driver/mysql/MysqlConnectionOptions"; + +describe("github issues > #6642 JoinTable does not respect inverseJoinColumns referenced column width", () => { + let connections: Connection[]; + + before(async () => { + return connections = await createTestingConnections({ + entities: [__dirname + "/entity/v1/*{.js,.ts}"], + schemaCreate: true, + dropSchema: true, + enabledDrivers: ["mysql"] + }); + }); + beforeEach(async () => await reloadTestingDatabases(connections)); + after(async () => await closeTestingConnections(connections)); + + it("should generate column widths equal to the referenced column widths", async () => { + + await Promise.all(connections.map(async (connection) => { + const options = setupSingleTestingConnection( + connection.options.type, + { + name: `${connection.name}-v2`, + entities: [__dirname + "/entity/v2/*{.js,.ts}"], + dropSchema: false, + schemaCreate: false + } + ) as MysqlConnectionOptions; + + if (!options) { + await connection.close(); + fail(); + } + + const migrationConnection = await createConnection(options); + try { + const sqlInMemory = await migrationConnection.driver + .createSchemaBuilder() + .log(); + + const upQueries = sqlInMemory.upQueries.map( + (query: Query) => query.query + ); + + upQueries.should.eql([ + "CREATE TABLE `foo_bars` (`foo_id` int(10) UNSIGNED NOT NULL, `bar_id` int(10) UNSIGNED NOT NULL, INDEX `IDX_319290776f044043e3ef3ba5a8` (`foo_id`), INDEX `IDX_b7fd4be386fa7cdb87ef8b12b6` (`bar_id`), PRIMARY KEY (`foo_id`, `bar_id`)) ENGINE=InnoDB", + "ALTER TABLE `foo_bars` ADD CONSTRAINT `FK_319290776f044043e3ef3ba5a8d` FOREIGN KEY (`foo_id`) REFERENCES `foo_entity`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION", + "ALTER TABLE `foo_bars` ADD CONSTRAINT `FK_b7fd4be386fa7cdb87ef8b12b69` FOREIGN KEY (`bar_id`) REFERENCES `bar_entity`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION" + ]); + + } finally { + await connection.close(); + await migrationConnection.close(); + } + })); + }); +}); diff --git a/test/github-issues/6699/issue-6699.ts b/test/github-issues/6699/issue-6699.ts new file mode 100644 index 0000000000..b7f6d525c1 --- /dev/null +++ b/test/github-issues/6699/issue-6699.ts @@ -0,0 +1,30 @@ +import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; +import {Connection} from "../../../src/connection/Connection"; +import {expect} from 'chai'; + +describe("github issues > #6699 MaxListenersExceededWarning occurs on Postgres", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [], + enabledDrivers: ["postgres"] + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it("queries in a transaction do not cause an EventEmitter memory leak", () => Promise.all(connections.map(async connection => { + await connection.transaction(async manager => { + const queryPromises = [...Array(10)].map( + () => manager.query('SELECT pg_sleep(0.0001)') + ); + + const pgConnection = await manager.queryRunner!.connect(); + + expect(pgConnection.listenerCount('error')).to.equal(1); + + // Wait for all of the queries to finish and drain the backlog + await Promise.all(queryPromises); + }); + }))); + +}); diff --git a/test/github-issues/6714/entity/session.ts b/test/github-issues/6714/entity/session.ts new file mode 100644 index 0000000000..9ea05da3ac --- /dev/null +++ b/test/github-issues/6714/entity/session.ts @@ -0,0 +1,17 @@ +import { Entity, PrimaryGeneratedColumn, Column } from "../../../../src"; + +@Entity({ name: "Session" }) +export class Session { + + @PrimaryGeneratedColumn() + id?: number; + + @Column({ + type: "timestamp", + precision: 3, + default: () => "CURRENT_TIMESTAMP(3)", + onUpdate: "CURRENT_TIMESTAMP(3)", + }) + ts: Date; + +} diff --git a/test/github-issues/6714/entity/sessionchanged.ts b/test/github-issues/6714/entity/sessionchanged.ts new file mode 100644 index 0000000000..c689295e84 --- /dev/null +++ b/test/github-issues/6714/entity/sessionchanged.ts @@ -0,0 +1,15 @@ +import { Entity, PrimaryGeneratedColumn, Column } from "../../../../src"; + +@Entity({ name: "Session" }) +export class Session { + @PrimaryGeneratedColumn() + id?: number; + + @Column({ + type: "timestamp", + precision: 4, + default: () => "CURRENT_TIMESTAMP(4)", + onUpdate: "CURRENT_TIMESTAMP(4)", + }) + ts: Date; +} diff --git a/test/github-issues/6714/issue-6714.ts b/test/github-issues/6714/issue-6714.ts new file mode 100644 index 0000000000..e51fd4a718 --- /dev/null +++ b/test/github-issues/6714/issue-6714.ts @@ -0,0 +1,59 @@ +import "reflect-metadata"; +import { + createTestingConnections, + closeTestingConnections, + reloadTestingDatabases, +} from "../../utils/test-utils"; +import { Connection } from "../../../src/connection/Connection"; +import { expect } from "chai"; +import { Session as baseEntity } from "./entity/session"; +import { Session as changedEntity } from "./entity/sessionchanged"; + +describe("github issues > #6714 Migration:generate issue with onUpdate using mariadb 10.4", () => { + it("dont change anything", async () => { + let connections: Connection[]; + connections = await createTestingConnections({ + entities: [baseEntity], + schemaCreate: false, + dropSchema: true, + enabledDrivers: ["mariadb"], + }); + await reloadTestingDatabases(connections); + await Promise.all( + connections.map(async (connection) => { + const schemaBuilder = connection.driver.createSchemaBuilder(); + const syncQueries = await schemaBuilder.log(); + expect(syncQueries.downQueries).to.be.eql([]); + expect(syncQueries.upQueries).to.be.eql([]); + }) + ); + await closeTestingConnections(connections); + }); + it("recognizing on update changes", async () => { + // this connection create database with a Session entity + const baseConnections = await createTestingConnections({ + entities: [baseEntity], + schemaCreate: true, // create the database + dropSchema: true, + enabledDrivers: ["mariadb"], + }); + // this connection change Session entity on update value + const connections = await createTestingConnections({ + entities: [changedEntity], + schemaCreate: false, // don't change the entity + dropSchema: false, + enabledDrivers: ["mariadb"], + name: "test", + }); + await Promise.all( + connections.map(async (connection) => { + const schemaBuilder = connection.driver.createSchemaBuilder(); + const syncQueries = await schemaBuilder.log(); + expect(syncQueries.downQueries.length).not.to.be.eql(0); + expect(syncQueries.upQueries.length).not.to.be.eql(0); + }) + ); + await closeTestingConnections(baseConnections); + await closeTestingConnections(connections); + }); +}); diff --git a/test/github-issues/798/issue-798.ts b/test/github-issues/798/issue-798.ts index 445cbb3126..34a05c6775 100644 --- a/test/github-issues/798/issue-798.ts +++ b/test/github-issues/798/issue-798.ts @@ -28,4 +28,11 @@ describe("github issues > #798 sqlite: 'database' path in ormconfig.json is not assert.strictEqual(connection.isConnected, true); }); + it("should find the sqlite database if the cwd is changed for better-sqlite3", async function () { + const options = await getConnectionOptions("better-sqlite3"); + connection = await createConnection(options); + + assert.strictEqual(connection.isConnected, true); + }); + }); \ No newline at end of file diff --git a/test/github-issues/799/issue-799.ts b/test/github-issues/799/issue-799.ts index 13f15f3396..d87a1c2ec4 100644 --- a/test/github-issues/799/issue-799.ts +++ b/test/github-issues/799/issue-799.ts @@ -1,7 +1,7 @@ import "reflect-metadata"; import * as assert from "assert"; import {createConnection} from "../../../src/index"; -import * as rimraf from "rimraf"; +import rimraf from "rimraf"; import {dirname} from "path"; import {Connection} from "../../../src/connection/Connection"; @@ -34,4 +34,14 @@ describe("github issues > #799 sqlite: 'database' path should be created", () => assert.strictEqual(connection.isConnected, true); }); + it("should create the whole path to database file for better-sqlite3", async function () { + connection = await createConnection({ + "name": "better-sqlite3", + "type": "better-sqlite3", + "database": path + }); + + assert.strictEqual(connection.isConnected, true); + }); + }); diff --git a/test/other-issues/mongodb-entity-change-in-subscribers/mongodb-entity-change-in-subscribers.ts b/test/other-issues/mongodb-entity-change-in-subscribers/mongodb-entity-change-in-subscribers.ts index 5dacc59257..69865b28da 100644 --- a/test/other-issues/mongodb-entity-change-in-subscribers/mongodb-entity-change-in-subscribers.ts +++ b/test/other-issues/mongodb-entity-change-in-subscribers/mongodb-entity-change-in-subscribers.ts @@ -35,7 +35,7 @@ describe("other issues > mongodb entity change in subscribers should affect pers const loadedUpdatedPost = await connection.manager.findOne(Post); expect(loadedUpdatedPost).not.to.be.undefined; expect(loadedUpdatedPost!.title).to.equals("hello world!"); - expect(loadedUpdatedPost!.updatedColumns).to.equals(3); // it actually should be 2, but ObjectId column always added + expect(loadedUpdatedPost!.updatedColumns).to.equals(4); // it actually should be 3, but ObjectId column always added await connection.manager.save(loadedPost!); diff --git a/test/other-issues/preventing-injection/preventing-injection.ts b/test/other-issues/preventing-injection/preventing-injection.ts index 36ef7889e1..bc45d88c9c 100644 --- a/test/other-issues/preventing-injection/preventing-injection.ts +++ b/test/other-issues/preventing-injection/preventing-injection.ts @@ -3,6 +3,7 @@ import {closeTestingConnections, createTestingConnections, reloadTestingDatabase import {Connection} from "../../../src"; import {Post} from "./entity/Post"; import {expect} from "chai"; +import {EntityColumnNotFound} from "../../../src/error/EntityColumnNotFound"; describe("other issues > preventing-injection", () => { @@ -28,7 +29,7 @@ describe("other issues > preventing-injection", () => { }).should.be.rejected; }))); - it("should not allow using non-exist columns in where expression", () => Promise.all(connections.map(async function(connection) { + it("should throw error for non-exist columns in where expression via FindOptions", () => Promise.all(connections.map(async function(connection) { const post = new Post(); post.title = "hello"; await connection.manager.save(post); @@ -40,12 +41,18 @@ describe("other issues > preventing-injection", () => { }); postWithOnlyIdSelected.should.be.eql([{ id: 1, title: "hello" }]); - await connection.manager.find(Post, { - where: { - id: 2, - ["(WHERE LIMIT 1)" as any]: "hello" - } - }).should.be.rejected; + let error: Error | undefined; + try { + await connection.manager.find(Post, { + where: { + id: 2, + ["(WHERE LIMIT 1)" as any]: "hello" + } + }); + } catch (err) { + error = err; + } + expect(error).to.be.an.instanceof(EntityColumnNotFound); }))); it("should not allow selection of non-exist columns via FindOptions", () => Promise.all(connections.map(async function(connection) { diff --git a/test/utils/test-utils.ts b/test/utils/test-utils.ts index 8706c32cde..22679a3a54 100644 --- a/test/utils/test-utils.ts +++ b/test/utils/test-utils.ts @@ -6,9 +6,9 @@ import {DatabaseType} from "../../src/driver/types/DatabaseType"; import {EntitySchema} from "../../src/entity-schema/EntitySchema"; import {createConnections} from "../../src/index"; import {NamingStrategyInterface} from "../../src/naming-strategy/NamingStrategyInterface"; -import {PromiseUtils} from "../../src/util/PromiseUtils"; import {EntityFactoryInterface} from "../../src/entity-factory/EntityFactoryInterface"; import {QueryResultCache} from "../../src/cache/QueryResultCache"; +import {Logger} from "../../src/logger/Logger"; /** * Interface in which data is stored in ormconfig.json of the project. @@ -139,6 +139,11 @@ export interface TestingOptions { * They are passed down to the enabled drivers. */ driverSpecific?: Object; + + /** + * Factory to create a logger for each test connection. + */ + createLogger?: () => "advanced-console"|"simple-console"|"file"|"debug"|Logger; } /** @@ -225,6 +230,8 @@ export function setupTestingConnections(options?: TestingOptions): ConnectionOpt newOptions.schema = options.schema; if (options && options.logging !== undefined) newOptions.logging = options.logging; + if (options && options.createLogger !== undefined) + newOptions.logger = options.createLogger(); if (options && options.__dirname) newOptions.entities = [options.__dirname + "/entity/*{.js,.ts}"]; if (options && options.__dirname) @@ -252,12 +259,12 @@ export async function createTestingConnections(options?: TestingOptions): Promis }); const queryRunner = connection.createQueryRunner(); - await PromiseUtils.runInSequence(databases, database => { - if (!(connection.driver instanceof PostgresDriver)) - return queryRunner.createDatabase(database, true); - return Promise.resolve(); - }); + for (const database of databases) { + if (!(connection.driver instanceof PostgresDriver)) { + await queryRunner.createDatabase(database, true); + } + } // create new schemas if (connection.driver instanceof PostgresDriver || connection.driver instanceof SqlServerDriver) { @@ -274,7 +281,9 @@ export async function createTestingConnections(options?: TestingOptions): Promis if (schema && schemaPaths.indexOf(schema) === -1) schemaPaths.push(schema); - await PromiseUtils.runInSequence(schemaPaths, schemaPath => queryRunner.createSchema(schemaPath, true)); + for (const schemaPath of schemaPaths) { + await queryRunner.createSchema(schemaPath, true); + } } await queryRunner.release(); diff --git a/tsconfig.json b/tsconfig.json index 3c4f1915bb..bc15dd86a8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,6 +2,8 @@ "version": "2.1.1", "compilerOptions": { "outDir": "build/compiled", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, "target": "ES2017", "module": "commonjs", "moduleResolution": "node", @@ -17,6 +19,7 @@ "pretty": true, "strictNullChecks": true, "noUnusedLocals": true, + "downlevelIteration": true }, "exclude": [ "tmp", diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 550a8cf6e2..0000000000 --- a/tslint.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "rules": { - "class-name": true, - "comment-format": [ - true, - "check-space" - ], - "indent": [ - true, - "spaces" - ], - "no-unused-variable": true, - "no-duplicate-variable": true, - "no-eval": true, - "no-internal-module": true, - "no-var-keyword": true, - "one-line": [ - true, - "check-open-brace", - "check-whitespace" - ], - "quotemark": [ - true, - "double" - ], - "semicolon": true, - "triple-equals": [ - true, - "allow-null-check" - ], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - } - ], - "variable-name": [ - true, - "ban-keywords" - ], - "whitespace": [ - true, - "check-branch", - "check-decl", - "check-operator", - "check-separator", - "check-type" - ] - } -} \ No newline at end of file