diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89e6c4d486d5..9a1d127fd6eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,45 +15,82 @@ jobs: name: Lint code and docs runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: - node-version: 16.x - - run: yarn install --frozen-lockfile + node-version: 18.x + - run: yarn global add node-gyp --ignore-engines + - run: yarn install --frozen-lockfile --ignore-engines - run: yarn lint - run: yarn lint-docs docs: name: Generate docs runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: - node-version: 16.x - - run: yarn install --frozen-lockfile + node-version: 18.x + - run: yarn global add node-gyp --ignore-engines + - run: yarn install --frozen-lockfile --ignore-engines - run: yarn docs test-typings: strategy: fail-fast: false matrix: - ts-version: ["4.1", "4.2", "4.3", "4.4", "4.5"] + ts-version: ["4.1", "4.2", "4.3", "4.4", "4.5", "4.6", "4.7", "4.8", "4.9", "5.0", "5.1", "5.2"] name: TS Typings (${{ matrix.ts-version }}) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: - node-version: 16.x - - run: yarn install --frozen-lockfile - - run: yarn add --dev typescript@~${{ matrix.ts-version }} + node-version: 18.x + - run: yarn global add node-gyp --ignore-engines + - run: yarn install --frozen-lockfile --ignore-engines + - run: yarn add --dev typescript@~${{ matrix.ts-version }} --ignore-engines - run: yarn test-typings + test-oracle: + strategy: + fail-fast: false + matrix: + oracle-version: [18, 23] + node-version: [10, 18] + name: Oracle DB ${{ matrix.oracle-version }} (Node ${{ matrix.node-version }}) + runs-on: ubuntu-22.04 + env: + DIALECT: oracle + SEQ_ORACLE_USER: sequelizetest + SEQ_ORACLE_PW: sequelizepassword + SEQ_ORACLE_DB: XEPDB1 + SEQ_ORACLE_HOST: localhost + SEQ_ORACLE_PORT: 1521 + LD_LIBRARY_PATH: ${{ github.workspace }}/.oracle/instantclient + UV_THREADPOOL_SIZE: 128 + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - run: yarn global add node-gyp --ignore-engines + - run: yarn install --frozen-lockfile --ignore-engines + - if: matrix.oracle-version == '18' + name: Install Local Oracle DB 18 + run: yarn start-oracle-oldest + - if: matrix.oracle-version == '23' + name: Install Local Oracle DB 23 + run: yarn start-oracle-latest + - name: Unit Tests + run: yarn test-unit + - name: Integration Tests + run: yarn test-integration test-db2: strategy: fail-fast: false matrix: - node-version: [10, 16] + node-version: [10, 18] name: DB2 (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 env: DIALECT: db2 SEQ_DB: testdb @@ -62,10 +99,11 @@ jobs: SEQ_TEST_CLEANUP_TIMEOUT: 1200000 SEQ_PORT: 50000 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} + - run: yarn global add node-gyp --ignore-engines - run: yarn install --frozen-lockfile --ignore-engines - name: Install Local DB2 Copy run: yarn start-db2 @@ -79,16 +117,17 @@ jobs: strategy: fail-fast: false matrix: - node-version: [10, 16] + node-version: [10, 18] name: SQLite (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 env: DIALECT: sqlite steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} + - run: yarn global add node-gyp --ignore-engines - run: yarn install --frozen-lockfile --ignore-engines - name: Unit Tests run: yarn test-unit @@ -98,12 +137,12 @@ jobs: strategy: fail-fast: false matrix: - node-version: [10, 16] + node-version: [10, 18] postgres-version: [9.5, 10] # Does not work with 12 minify-aliases: [true, false] native: [true, false] name: Postgres ${{ matrix.postgres-version }}${{ matrix.native && ' (native)' || '' }} (Node ${{ matrix.node-version }})${{ matrix.minify-aliases && ' (minified aliases)' || '' }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 services: postgres: image: sushantdhiman/postgres:${{ matrix.postgres-version }} @@ -120,10 +159,11 @@ jobs: SEQ_PG_MINIFY_ALIASES: ${{ matrix.minify-aliases && '1' || '' }} steps: - run: PGPASSWORD=sequelize_test psql -h localhost -p 5432 -U sequelize_test sequelize_test -c '\l' - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} + - run: yarn global add node-gyp --ignore-engines - run: yarn install --frozen-lockfile --ignore-engines - run: yarn add pg-native --ignore-engines if: matrix.native @@ -144,7 +184,7 @@ jobs: - name: MySQL 5.7 image: mysql:5.7 dialect: mysql - node-version: 16 + node-version: 18 - name: MySQL 8.0 image: mysql:8.0 dialect: mysql @@ -152,7 +192,7 @@ jobs: - name: MySQL 8.0 image: mysql:8.0 dialect: mysql - node-version: 16 + node-version: 18 - name: MariaDB 10.3 image: mariadb:10.3 dialect: mariadb @@ -160,7 +200,7 @@ jobs: - name: MariaDB 10.3 image: mariadb:10.3 dialect: mariadb - node-version: 16 + node-version: 18 - name: MariaDB 10.5 image: mariadb:10.5 dialect: mariadb @@ -168,9 +208,9 @@ jobs: - name: MariaDB 10.5 image: mariadb:10.5 dialect: mariadb - node-version: 16 + node-version: 18 name: ${{ matrix.name }} (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 services: mysql: image: ${{ matrix.image }} @@ -187,10 +227,11 @@ jobs: DIALECT: ${{ matrix.dialect }} steps: - run: mysql --host 127.0.0.1 --port 3306 -uroot -psequelize_test -e "GRANT ALL ON *.* TO 'sequelize_test'@'%' with grant option; FLUSH PRIVILEGES;" - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} + - run: yarn global add node-gyp --ignore-engines - run: yarn install --frozen-lockfile --ignore-engines - name: Unit Tests run: yarn test-unit @@ -200,20 +241,21 @@ jobs: strategy: fail-fast: false matrix: - node-version: [10, 16] + node-version: [10, 18] mssql-version: [2017, 2019] name: MSSQL ${{ matrix.mssql-version }} (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 services: mssql: image: mcr.microsoft.com/mssql/server:${{ matrix.mssql-version }}-latest env: ACCEPT_EULA: Y SA_PASSWORD: Password12! + MSSQL_SA_PASSWORD: Password12! ports: - 1433:1433 options: >- - --health-cmd="/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P \"Password12!\" -l 30 -Q \"SELECT 1\"" + --health-cmd="/opt/mssql-tools${{ matrix.mssql-version == '2019' && '18' || '' }}/bin/sqlcmd -S localhost -U SA -P \"Password12!\" -C -l 30 -Q \"SELECT 1\"" --health-start-period 10s --health-interval 10s --health-timeout 5s @@ -224,11 +266,12 @@ jobs: SEQ_PW: Password12! SEQ_PORT: 1433 steps: - - run: /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "Password12!" -Q "CREATE DATABASE sequelize_test; ALTER DATABASE sequelize_test SET READ_COMMITTED_SNAPSHOT ON;" - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - run: /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "Password12!" -C -Q "CREATE DATABASE sequelize_test; ALTER DATABASE sequelize_test SET READ_COMMITTED_SNAPSHOT ON;" + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} + - run: yarn global add node-gyp --ignore-engines - run: yarn install --frozen-lockfile --ignore-engines - name: Unit Tests run: yarn test-unit @@ -238,16 +281,17 @@ jobs: strategy: fail-fast: false matrix: - node-version: [10, 16] + node-version: [10, 18] name: SNOWFLAKE (Node ${{ matrix.node-version }}) - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 env: DIALECT: snowflake steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} + - run: yarn global add node-gyp --ignore-engines - run: yarn install --frozen-lockfile --ignore-engines - name: Unit Tests run: yarn test-unit @@ -264,7 +308,6 @@ jobs: test-sqlite, test-postgres, test-mysql-mariadb, - test-mssql, ] if: github.event_name == 'push' && (github.ref == 'refs/heads/v6' || github.ref == 'refs/heads/v6-beta') env: @@ -272,10 +315,11 @@ jobs: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v3 with: - node-version: 16.x - - run: yarn install --frozen-lockfile + node-version: 18.x + - run: yarn global add node-gyp --ignore-engines + - run: yarn install --frozen-lockfile --ignore-engines - run: npx semantic-release - id: sequelize uses: sdepold/github-action-get-latest-release@master diff --git a/.gitignore b/.gitignore index 2544c8581afe..54389f25c6e5 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ esdoc node_modules /lib /types +.oracle/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cb2cd52d453d..479465728745 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ We are happy to see that you might be interested in contributing to Sequelize! T - Reviewing (i.e. commenting on) open Pull Requests, to help their creators improve it if needed and allow maintainers to take less time looking into them - Helping to clarify issues opened by others, commenting and asking for clarification - Answering [questions tagged with `sequelize.js` on StackOverflow](https://stackoverflow.com/questions/tagged/sequelize.js) -- Helping people in our [public Slack channel](https://sequelize.slack.com/) (note: if you don't have access, get yourself an invite automatically via [this link](http://sequelize-slack.herokuapp.com/)) +- Helping people in our [public Slack channel](https://sequelize.slack.com/) (note: if you don't have access, get yourself an invite automatically via [this link](https://sequelize.org/slack)) Sequelize is strongly moved by contributions from people like you. All maintainers also work on their free time here. diff --git a/README.md b/README.md index cd9db8121f61..3bc983b542ae 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,83 @@

- -

Sequelize

+ Sequelize logo +

Sequelize

[![npm version](https://badgen.net/npm/v/sequelize)](https://www.npmjs.com/package/sequelize) [![Build Status](https://github.com/sequelize/sequelize/workflows/CI/badge.svg)](https://github.com/sequelize/sequelize/actions?query=workflow%3ACI) [![npm downloads](https://badgen.net/npm/dm/sequelize)](https://www.npmjs.com/package/sequelize) +[![contributors](https://img.shields.io/github/contributors/sequelize/sequelize)](https://github.com/sequelize/sequelize/graphs/contributors) +[![Open Collective](https://img.shields.io/opencollective/backers/sequelize)](https://opencollective.com/sequelize#section-contributors) [![sponsor](https://img.shields.io/opencollective/all/sequelize?label=sponsors)](https://opencollective.com/sequelize) [![Merged PRs](https://badgen.net/github/merged-prs/sequelize/sequelize)](https://github.com/sequelize/sequelize) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -Sequelize is a promise-based [Node.js](https://nodejs.org/en/about/) [ORM tool](https://en.wikipedia.org/wiki/Object-relational_mapping) for [Postgres](https://en.wikipedia.org/wiki/PostgreSQL), [MySQL](https://en.wikipedia.org/wiki/MySQL), [MariaDB](https://en.wikipedia.org/wiki/MariaDB), [SQLite](https://en.wikipedia.org/wiki/SQLite), [DB2](https://en.wikipedia.org/wiki/IBM_Db2_Family) and [Microsoft SQL Server](https://en.wikipedia.org/wiki/Microsoft_SQL_Server). It features solid transaction support, relations, eager and lazy loading, read replication and more. +Sequelize is an easy-to-use and promise-based [Node.js](https://nodejs.org/en/about/) [ORM tool](https://en.wikipedia.org/wiki/Object-relational_mapping) for [Postgres](https://en.wikipedia.org/wiki/PostgreSQL), [MySQL](https://en.wikipedia.org/wiki/MySQL), [MariaDB](https://en.wikipedia.org/wiki/MariaDB), [SQLite](https://en.wikipedia.org/wiki/SQLite), [DB2](https://en.wikipedia.org/wiki/IBM_Db2_Family), [Microsoft SQL Server](https://en.wikipedia.org/wiki/Microsoft_SQL_Server), and [Snowflake](https://www.snowflake.com/). It features solid transaction support, relations, eager and lazy loading, read replication and more. -Sequelize follows [Semantic Versioning](http://semver.org) and supports Node v10 and above. +Would you like to contribute? Read [our contribution guidelines](https://github.com/sequelize/sequelize/blob/main/CONTRIBUTING.md) to know more. There are many ways to help! 😃 -New to Sequelize? Take a look at the [Tutorials and Guides](https://sequelize.org/master). You might also be interested in the [API Reference](https://sequelize.org/master/identifiers). +## 🚀 Seeking New Maintainers for Sequelize! 🚀 -Would you like to contribute? Read [our contribution guidelines](https://github.com/sequelize/sequelize/blob/main/CONTRIBUTING.md) to know more. There are many ways to help. +We're looking for new maintainers to help finalize and release the next major version of Sequelize! If you're passionate about open-source and database ORMs, we'd love to have you onboard. -### v6 Release +### 💰 Funding Available +We distribute **$2,500 per quarter** among maintainers and have additional funds for full-time contributions. -You can find the detailed changelog [here](https://github.com/sequelize/sequelize/blob/main/docs/manual/other-topics/upgrade-to-v6.md). +### 🛠️ What You’ll Work On +- Finalizing and releasing Sequelize’s next major version +- Improving TypeScript support and database integrations +- Fixing critical issues and shaping the ORM’s future -## Supporting the project +### 🤝 How to Get Involved +Interested? Join our Slack and reach out to **@WikiRik** or **@sdepold**: +➡️ **[sequelize.org/slack](https://sequelize.org/slack)** -Do you like Sequelize and would like to give back to the engineering team behind it? +We’d love to have you on board! 🚀 -We have recently created an [OpenCollective based money pool](https://opencollective.com/sequelize) which is shared amongst all core maintainers based on their contributions. Every support is wholeheartedly welcome. ❤️ +## :computer: Getting Started + +Ready to start using Sequelize? Head to [sequelize.org](https://sequelize.org) to begin! -## Installation +- [Our Getting Started guide for Sequelize 6 (stable)](https://sequelize.org/docs/v6/getting-started) -```sh -$ npm i sequelize # This will install v6 +## :money_with_wings: Supporting the project -# And one of the following: -$ npm i pg pg-hstore # Postgres -$ npm i mysql2 -$ npm i mariadb -$ npm i sqlite3 -$ npm i tedious # Microsoft SQL Server -$ npm i ibm_db #DB2 -``` +Do you like Sequelize and would like to give back to the engineering team behind it? -## Documentation +We have recently created an [OpenCollective based money pool](https://opencollective.com/sequelize) which is shared amongst all core maintainers based on their contributions. Every support is wholeheartedly welcome. ❤️ -- [v6 Documentation](https://sequelize.org/master) -- [v5/v4/v3 Documentation](https://sequelize.org) -- [Contributing](https://github.com/sequelize/sequelize/blob/main/CONTRIBUTING.md) +## :pencil: Major version changelog -## Responsible disclosure +Please find upgrade information to major versions here: -If you have security issues to report, please refer to our [Responsible Disclosure Policy](https://github.com/sequelize/sequelize/blob/main/SECURITY.md) for more details. +- [Upgrade from v5 to v6](https://sequelize.org/docs/v6/other-topics/upgrade-to-v6) -## Resources +## :book: Resources +- [Documentation](https://sequelize.org) +- [Databases Compatibility Table](https://sequelize.org/releases/) - [Changelog](https://github.com/sequelize/sequelize/releases) -- [Slack Inviter](http://sequelize-slack.herokuapp.com/) +- [Discussions](https://github.com/sequelize/sequelize/discussions) +- [Slack](https://sequelize.org/slack) - [Stack Overflow](https://stackoverflow.com/questions/tagged/sequelize.js) -### Tools +### :wrench: Tools - [CLI](https://github.com/sequelize/cli) -- [With TypeScript](https://sequelize.org/master/manual/typescript.html) +- [With TypeScript](https://sequelize.org/docs/v6/other-topics/typescript) - [Enhanced TypeScript with decorators](https://github.com/RobinBuschmann/sequelize-typescript) - [For GraphQL](https://github.com/mickhansen/graphql-sequelize) - [For CockroachDB](https://github.com/cockroachdb/sequelize-cockroachdb) -- [Plugins](https://sequelize.org/master/manual/resources.html) +- [Awesome Sequelize](https://sequelize.org/docs/v6/other-topics/resources/) - [For YugabyteDB](https://github.com/yugabyte/sequelize-yugabytedb) -### Translations +### :speech_balloon: Translations + +- [English](https://sequelize.org) (Official) +- [中文文档](https://github.com/demopark/sequelize-docs-Zh-CN) (Unofficial) -- [English](https://sequelize.org/master) (OFFICIAL) -- [中文文档](https://github.com/demopark/sequelize-docs-Zh-CN) (UNOFFICIAL) +## :warning: Responsible disclosure +If you have security issues to report, please refer to our +[Responsible Disclosure Policy](https://github.com/sequelize/sequelize/blob/main/SECURITY.md) for more details. diff --git a/dev/mariadb/10.3/start.sh b/dev/mariadb/10.3/start.sh index 30af181cb667..492b19bca12e 100755 --- a/dev/mariadb/10.3/start.sh +++ b/dev/mariadb/10.3/start.sh @@ -3,8 +3,8 @@ set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 -docker-compose -p sequelize-mariadb-103 down --remove-orphans -docker-compose -p sequelize-mariadb-103 up -d +docker compose -p sequelize-mariadb-103 down --remove-orphans +docker compose -p sequelize-mariadb-103 up -d ./../../wait-until-healthy.sh sequelize-mariadb-103 diff --git a/dev/mariadb/10.3/stop.sh b/dev/mariadb/10.3/stop.sh index e2629c115979..bee20b8ff7bd 100755 --- a/dev/mariadb/10.3/stop.sh +++ b/dev/mariadb/10.3/stop.sh @@ -3,6 +3,6 @@ set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 -docker-compose -p sequelize-mariadb-103 down --remove-orphans +docker compose -p sequelize-mariadb-103 down --remove-orphans echo "Local MariaDB-10.3 instance stopped (if it was running)." diff --git a/dev/mssql/2019/start.sh b/dev/mssql/2019/start.sh index 9fe3c2b48997..61ec91ac623a 100755 --- a/dev/mssql/2019/start.sh +++ b/dev/mssql/2019/start.sh @@ -3,14 +3,14 @@ set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 -docker-compose -p sequelize-mssql-2019 down --remove-orphans -docker-compose -p sequelize-mssql-2019 up -d +docker compose -p sequelize-mssql-2019 down --remove-orphans +docker compose -p sequelize-mssql-2019 up -d ./../../wait-until-healthy.sh sequelize-mssql-2019 docker exec sequelize-mssql-2019 \ /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "Password12!" -Q "CREATE DATABASE sequelize_test; ALTER DATABASE sequelize_test SET READ_COMMITTED_SNAPSHOT ON;" -node check.js +DIALECT=mssql node check.js echo "Local MSSQL-2019 instance is ready for Sequelize tests." diff --git a/dev/mssql/2019/stop.sh b/dev/mssql/2019/stop.sh index 0c8d73b3fee1..10249f0e619d 100755 --- a/dev/mssql/2019/stop.sh +++ b/dev/mssql/2019/stop.sh @@ -3,6 +3,6 @@ set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 -docker-compose -p sequelize-mssql-2019 down --remove-orphans +docker compose -p sequelize-mssql-2019 down --remove-orphans echo "Local MSSQL-2019 instance stopped (if it was running)." diff --git a/dev/mysql/5.7/start.sh b/dev/mysql/5.7/start.sh index fb8b02a8b43d..8ef78e301c16 100755 --- a/dev/mysql/5.7/start.sh +++ b/dev/mysql/5.7/start.sh @@ -3,8 +3,8 @@ set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 -docker-compose -p sequelize-mysql-57 down --remove-orphans -docker-compose -p sequelize-mysql-57 up -d +docker compose -p sequelize-mysql-57 down --remove-orphans +docker compose -p sequelize-mysql-57 up -d ./../../wait-until-healthy.sh sequelize-mysql-57 diff --git a/dev/mysql/5.7/stop.sh b/dev/mysql/5.7/stop.sh index 36e3e076065e..60c6a7b3d868 100755 --- a/dev/mysql/5.7/stop.sh +++ b/dev/mysql/5.7/stop.sh @@ -3,6 +3,6 @@ set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 -docker-compose -p sequelize-mysql-57 down --remove-orphans +docker compose -p sequelize-mysql-57 down --remove-orphans echo "Local MySQL-5.7 instance stopped (if it was running)." diff --git a/dev/mysql/8.0/start.sh b/dev/mysql/8.0/start.sh index d3b0aaab912c..046ba95d145b 100755 --- a/dev/mysql/8.0/start.sh +++ b/dev/mysql/8.0/start.sh @@ -3,8 +3,8 @@ set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 -docker-compose -p sequelize-mysql-80 down --remove-orphans -docker-compose -p sequelize-mysql-80 up -d +docker compose -p sequelize-mysql-80 down --remove-orphans +docker compose -p sequelize-mysql-80 up -d ./../../wait-until-healthy.sh sequelize-mysql-80 diff --git a/dev/mysql/8.0/stop.sh b/dev/mysql/8.0/stop.sh index a5a6492ca0f7..8bcf3da8323e 100755 --- a/dev/mysql/8.0/stop.sh +++ b/dev/mysql/8.0/stop.sh @@ -3,6 +3,6 @@ set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 -docker-compose -p sequelize-mysql-80 down --remove-orphans +docker compose -p sequelize-mysql-80 down --remove-orphans echo "Local MySQL-8.0 instance stopped (if it was running)." diff --git a/dev/oracle/18-slim/docker-compose.yml b/dev/oracle/18-slim/docker-compose.yml new file mode 100644 index 000000000000..1ba87e65e686 --- /dev/null +++ b/dev/oracle/18-slim/docker-compose.yml @@ -0,0 +1,17 @@ +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +services: + oraclexedb: + container_name: oraclexedb + image: gvenzl/oracle-xe:18-slim + environment: + ORACLE_PASSWORD: password + ports: + - 1521:1521 + healthcheck: + test: ["CMD-SHELL", "sqlplus", "system/password@XEPDB1"] + retries: 10 + +networks: + default: + name: sequelize-oraclexedb-network diff --git a/dev/oracle/18-slim/start.sh b/dev/oracle/18-slim/start.sh new file mode 100755 index 000000000000..aa0c719e1797 --- /dev/null +++ b/dev/oracle/18-slim/start.sh @@ -0,0 +1,61 @@ +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +#!/usr/bin/env bash +set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 + +# Remove an existing Oracle DB docker image +docker compose -p oraclexedb down --remove-orphans + +# Bring up new Oracle DB docker image +docker compose -p oraclexedb up -d + +# Wait until Oracle DB is set up and docker state is healthy +./../wait-until-healthy.sh oraclexedb + +# Moving privileges.sql to docker container +docker cp ../privileges.sql oraclexedb:/opt/oracle/. + +# Granting all the needed privileges to sequelizetest user +docker exec -t oraclexedb sqlplus system/password@XEPDB1 @privileges.sql + +SEQ_WORKSPACE="$PWD"/../../../ + +if [[ ! -d "$SEQ_WORKSPACE"/.oracle/ ]] +then + mkdir "$SEQ_WORKSPACE"/.oracle/ + if [[ $(uname) == 'Linux' ]] + then + wget https://download.oracle.com/otn_software/linux/instantclient/217000/instantclient-basic-linux.x64-21.7.0.0.0dbru.zip --no-check-certificate && + unzip instantclient-basic-linux.x64-21.7.0.0.0dbru.zip -d "$SEQ_WORKSPACE"/.oracle/ && + rm instantclient-basic-linux.x64-21.7.0.0.0dbru.zip && + mv "$SEQ_WORKSPACE"/.oracle/instantclient_21_7 "$SEQ_WORKSPACE"/.oracle/instantclient + + echo "Local Oracle instant client on Linux has been setup!" + elif [[ $(uname) == 'Darwin' ]] + then + if [[ ! -d ~/Downloads/instantclient_19_8 ]] + then + curl -O https://download.oracle.com/otn_software/mac/instantclient/198000/instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg && + hdiutil mount instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg && + /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru/install_ic.sh && + hdiutil unmount /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru && + rm instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg && + mv ~/Downloads/instantclient_19_8/ "$SEQ_WORKSPACE"/.oracle/instantclient + else + cp -rf ~/Downloads/instantclient_19_8/ "$SEQ_WORKSPACE"/.oracle/instantclient + fi + ln -s "$SEQ_WORKSPACE"/.oracle/instantclient/libclntsh.dylib "$SEQ_WORKSPACE"/node_modules/oracledb/build/Release/ + + echo "Local Oracle instant client on macOS has been setup!" + else + # Windows + curl -O https://download.oracle.com/otn_software/nt/instantclient/216000/instantclient-basic-windows.x64-21.6.0.0.0dbru.zip && + unzip instantclient-basic-windows.x64-21.6.0.0.0dbru.zip -d "$SEQ_WORKSPACE"/.oracle/ && + rm instantclient-basic-windows.x64-21.6.0.0.0dbru.zip && + mv "$SEQ_WORKSPACE"/.oracle/instantclient_21_6/* "$SEQ_WORKSPACE"/node_modules/oracledb/build/Release + + echo "Local Oracle instant client on $(uname) has been setup!" + fi +fi +echo "Local Oracle DB is ready for use!" diff --git a/dev/oracle/18-slim/stop.sh b/dev/oracle/18-slim/stop.sh new file mode 100755 index 000000000000..d3ac45b9a0c4 --- /dev/null +++ b/dev/oracle/18-slim/stop.sh @@ -0,0 +1,10 @@ +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +#!/usr/bin/env bash +set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 + + +docker compose -p oraclexedb down --remove-orphans + +echo "Local Oracle DB instance stopped (if it was running)." diff --git a/dev/oracle/23-slim/docker-compose.yml b/dev/oracle/23-slim/docker-compose.yml new file mode 100644 index 000000000000..95d8c749ed2e --- /dev/null +++ b/dev/oracle/23-slim/docker-compose.yml @@ -0,0 +1,19 @@ +# Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved + +services: + oraclexedb: + container_name: oraclexedb + image: gvenzl/oracle-free:23.4-slim + environment: + ORACLE_PASSWORD: password + ORACLE_DATABASE: XEPDB1 + + ports: + - 1521:1521 + healthcheck: + test: ["CMD-SHELL", "sqlplus", "system/password@localhost:1521/XEPDB1"] + retries: 10 + +networks: + default: + name: sequelize-oraclexedb-network diff --git a/dev/oracle/23-slim/start.sh b/dev/oracle/23-slim/start.sh new file mode 100755 index 000000000000..dd14eb1d476b --- /dev/null +++ b/dev/oracle/23-slim/start.sh @@ -0,0 +1,61 @@ +# Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved + +#!/usr/bin/env bash +set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 + +# Remove an existing Oracle DB docker image +docker compose -p oraclexedb down --remove-orphans + +# Bring up new Oracle DB docker image +docker compose -p oraclexedb up -d + +# Wait until Oracle DB is set up and docker state is healthy +./../wait-until-healthy.sh oraclexedb + +# Moving privileges.sql to docker container +docker cp ../privileges.sql oraclexedb:/opt/oracle/. + +# Granting all the needed privileges to sequelizetest user +docker exec -t oraclexedb sqlplus system/password@localhost:1521/XEPDB1 @privileges.sql + +SEQ_WORKSPACE="$PWD"/../../../ + +if [[ ! -d "$SEQ_WORKSPACE"/.oracle/ ]] +then + mkdir "$SEQ_WORKSPACE"/.oracle/ + if [[ $(uname) == 'Linux' ]] + then + wget https://download.oracle.com/otn_software/linux/instantclient/217000/instantclient-basic-linux.x64-21.7.0.0.0dbru.zip --no-check-certificate && + unzip instantclient-basic-linux.x64-21.7.0.0.0dbru.zip -d "$SEQ_WORKSPACE"/.oracle/ && + rm instantclient-basic-linux.x64-21.7.0.0.0dbru.zip && + mv "$SEQ_WORKSPACE"/.oracle/instantclient_21_7 "$SEQ_WORKSPACE"/.oracle/instantclient + + echo "Local Oracle instant client on Linux has been setup!" + elif [[ $(uname) == 'Darwin' ]] + then + if [[ ! -d ~/Downloads/instantclient_19_8 ]] + then + curl -O https://download.oracle.com/otn_software/mac/instantclient/198000/instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg && + hdiutil mount instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg && + /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru/install_ic.sh && + hdiutil unmount /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru && + rm instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg && + mv ~/Downloads/instantclient_19_8/ "$SEQ_WORKSPACE"/.oracle/instantclient + else + cp -rf ~/Downloads/instantclient_19_8/ "$SEQ_WORKSPACE"/.oracle/instantclient + fi + ln -s "$SEQ_WORKSPACE"/.oracle/instantclient/libclntsh.dylib "$SEQ_WORKSPACE"/node_modules/oracledb/build/Release/ + + echo "Local Oracle instant client on macOS has been setup!" + else + # Windows + curl -O https://download.oracle.com/otn_software/nt/instantclient/216000/instantclient-basic-windows.x64-21.6.0.0.0dbru.zip && + unzip instantclient-basic-windows.x64-21.6.0.0.0dbru.zip -d "$SEQ_WORKSPACE"/.oracle/ && + rm instantclient-basic-windows.x64-21.6.0.0.0dbru.zip && + mv "$SEQ_WORKSPACE"/.oracle/instantclient_21_6/* "$SEQ_WORKSPACE"/node_modules/oracledb/build/Release + + echo "Local Oracle instant client on $(uname) has been setup!" + fi +fi +echo "Local Oracle DB is ready for use!" diff --git a/dev/oracle/23-slim/stop.sh b/dev/oracle/23-slim/stop.sh new file mode 100755 index 000000000000..d3ac45b9a0c4 --- /dev/null +++ b/dev/oracle/23-slim/stop.sh @@ -0,0 +1,10 @@ +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +#!/usr/bin/env bash +set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ +cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 + + +docker compose -p oraclexedb down --remove-orphans + +echo "Local Oracle DB instance stopped (if it was running)." diff --git a/dev/oracle/privileges.sql b/dev/oracle/privileges.sql new file mode 100644 index 000000000000..afea910fdc49 --- /dev/null +++ b/dev/oracle/privileges.sql @@ -0,0 +1,27 @@ +-- Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +create user sequelizetest identified by sequelizepassword; +grant connect to sequelizetest with admin option; +grant create session to sequelizetest with admin option; +grant grant any privilege to sequelizetest with admin option; +grant grant any role to sequelizetest with admin option; +grant create any table to sequelizetest with admin option; +grant insert any table to sequelizetest with admin option; +grant select any table to sequelizetest with admin option; +grant update any table to sequelizetest with admin option; +grant delete any table to sequelizetest with admin option; +grant drop any table to sequelizetest with admin option; +grant create view to sequelizetest with admin option; +grant create user to sequelizetest with admin option; +grant drop user to sequelizetest with admin option; +grant create any trigger to sequelizetest with admin option; +grant create any procedure to sequelizetest with admin option; +grant create any sequence to sequelizetest with admin option; +grant select any sequence to sequelizetest with admin option; +grant drop any sequence to sequelizetest with admin option; +grant create any synonym to sequelizetest with admin option; +grant create any index to sequelizetest with admin option; +grant alter user to sequelizetest with admin option; +grant alter any table to sequelizetest with admin option; +alter user sequelizetest quota unlimited on users; +exit; diff --git a/dev/oracle/wait-until-healthy.sh b/dev/oracle/wait-until-healthy.sh new file mode 100755 index 000000000000..096242f82a05 --- /dev/null +++ b/dev/oracle/wait-until-healthy.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +if [ "$#" -ne 1 ]; then + >&2 echo "Please provide the container name or hash" + exit 1 +fi + +for _ in {1..50} +do + state=$(docker inspect -f '{{ .State.Health.Status }}' $1 2>&1) + return_code=$? + if [ ${return_code} -eq 0 ] && [ "$state" == "healthy" ]; then + echo "$1 is healthy!" + sleep 60 + exit 0 + fi + sleep 6 +done + +>&2 echo "Timeout of 5m exceeded when waiting for container to be healthy: $1" +exit 1 diff --git a/dev/postgres/10/start.sh b/dev/postgres/10/start.sh index 6a2ea51738e9..fe0dc41117f1 100755 --- a/dev/postgres/10/start.sh +++ b/dev/postgres/10/start.sh @@ -3,8 +3,8 @@ set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 -docker-compose -p sequelize-postgres-10 down --remove-orphans -docker-compose -p sequelize-postgres-10 up -d +docker compose -p sequelize-postgres-10 down --remove-orphans +docker compose -p sequelize-postgres-10 up -d ./../../wait-until-healthy.sh sequelize-postgres-10 diff --git a/dev/postgres/10/stop.sh b/dev/postgres/10/stop.sh index 907d2074513b..53dd5c47fbf7 100755 --- a/dev/postgres/10/stop.sh +++ b/dev/postgres/10/stop.sh @@ -3,6 +3,6 @@ set -Eeuxo pipefail # https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" # https://stackoverflow.com/a/17744637 -docker-compose -p sequelize-postgres-10 down --remove-orphans +docker compose -p sequelize-postgres-10 down --remove-orphans echo "Local Postgres-10 instance stopped (if it was running)." diff --git a/logo.svg b/logo.svg new file mode 100644 index 000000000000..0ee676a33cc8 --- /dev/null +++ b/logo.svg @@ -0,0 +1,41 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/package.json b/package.json index 2d37e64aec2e..bc69e634ae69 100644 --- a/package.json +++ b/package.json @@ -17,16 +17,26 @@ }, "homepage": "https://sequelize.org/", "main": "./lib/index.js", - "types": "./types", + "types": "./types/index.d.ts", "type": "commonjs", "exports": { ".": { + "types": "./types/index.d.ts", "import": "./lib/index.mjs", "require": "./lib/index.js" }, - "./lib/*": "./lib/*.js", - "./lib/errors": "./lib/errors/index.js", - "./*": "./*" + "./lib/*": { + "types": "./types/*.d.ts", + "default": "./lib/*.js" + }, + "./lib/errors": { + "types": "./types/errors/index.d.ts", + "default": "./lib/errors/index.js" + }, + "./package.json": "./package.json", + "./types/*": { + "types": "./types/*.d.ts" + } }, "engines": { "node": ">=10.0.0" @@ -38,21 +48,21 @@ ], "license": "MIT", "dependencies": { - "@types/debug": "^4.1.7", - "@types/validator": "^13.7.1", - "debug": "^4.3.3", - "dottie": "^2.0.2", - "inflection": "^1.13.2", + "@types/debug": "^4.1.8", + "@types/validator": "^13.7.17", + "debug": "^4.3.4", + "dottie": "^2.0.6", + "inflection": "^1.13.4", "lodash": "^4.17.21", - "moment": "^2.29.1", - "moment-timezone": "^0.5.34", - "pg-connection-string": "^2.5.0", - "retry-as-promised": "^5.0.0", - "semver": "^7.3.5", + "moment": "^2.29.4", + "moment-timezone": "^0.5.43", + "pg-connection-string": "^2.6.1", + "retry-as-promised": "^7.0.4", + "semver": "^7.5.4", "sequelize-pool": "^7.1.0", "toposort-class": "^1.0.1", "uuid": "^8.3.2", - "validator": "^13.7.0", + "validator": "^13.9.0", "wkx": "^0.5.0" }, "devDependencies": { @@ -61,14 +71,14 @@ "@octokit/rest": "^18.12.0", "@octokit/types": "^6.34.0", "@types/chai": "^4.3.0", - "@types/lodash": "4.14.182", + "@types/lodash": "4.14.197", "@types/mocha": "^9.0.0", "@types/node": "^16.11.17", "@types/sinon": "^10.0.6", "@typescript-eslint/eslint-plugin": "^5.8.1", "@typescript-eslint/parser": "^5.8.1", "acorn": "^8.7.0", - "chai": "^4.3.4", + "chai": "^4.3.7", "chai-as-promised": "^7.1.1", "chai-datetime": "^1.8.0", "cheerio": "^1.0.0-rc.10", @@ -99,6 +109,7 @@ "mysql2": "^2.3.3", "node-hook": "^1.0.0", "nyc": "^15.1.0", + "oracledb": "^5.5.0", "p-map": "^4.0.0", "p-props": "^4.0.0", "p-settle": "^4.1.1", @@ -112,7 +123,7 @@ "sinon-chai": "^3.7.0", "snowflake-sdk": "^1.6.6", "source-map-support": "^0.5.21", - "sqlite3": "npm:@vscode/sqlite3@^5.0.7", + "sqlite3": "^5.1.6", "tedious": "8.3.0", "typescript": "^4.5.4" }, @@ -140,6 +151,9 @@ }, "tedious": { "optional": true + }, + "oracledb": { + "optional": true } }, "keywords": [ @@ -153,6 +167,7 @@ "db2", "ibm_db", "sql", + "oracledb", "sqlserver", "snowflake", "orm", @@ -232,17 +247,23 @@ "start-postgres": "bash dev/postgres/10/start.sh", "start-mssql": "bash dev/mssql/2019/start.sh", "start-db2": "bash dev/db2/11.5/start.sh", + "start-oracle-oldest": "bash dev/oracle/18-slim/start.sh", + "start-oracle-latest": "bash dev/oracle/23-slim/start.sh", "stop-mariadb": "bash dev/mariadb/10.3/stop.sh", "stop-mysql": "bash dev/mysql/5.7/stop.sh", "stop-mysql-8": "bash dev/mysql/8.0/stop.sh", "stop-postgres": "bash dev/postgres/10/stop.sh", "stop-mssql": "bash dev/mssql/2019/stop.sh", "stop-db2": "bash dev/db2/11.5/stop.sh", + "stop-oracle-oldest": "bash dev/oracle/18-slim/stop.sh", + "stop-oracle-latest": "bash dev/oracle/23-slim/stop.sh", "restart-mariadb": "npm run start-mariadb", "restart-mysql": "npm run start-mysql", "restart-postgres": "npm run start-postgres", "restart-mssql": "npm run start-mssql", "restart-db2": "npm run start-db2", + "restart-oracle-oldest": "npm run start-oracle-oldest", + "restart-oracle-latest": "npm run start-oracle-latest", "----------------------------------------- local tests ---------------------------------------------": "", "test-unit-mariadb": "cross-env DIALECT=mariadb npm run test-unit", "test-unit-mysql": "cross-env DIALECT=mysql npm run test-unit", @@ -252,7 +273,8 @@ "test-unit-mssql": "cross-env DIALECT=mssql npm run test-unit", "test-unit-db2": "cross-env DIALECT=db2 npm run test-unit", "test-unit-snowflake": "cross-env DIALECT=snowflake npm run test-unit", - "test-unit-all": "npm run test-unit-mariadb && npm run test-unit-mysql && npm run test-unit-postgres && npm run test-unit-postgres-native && npm run test-unit-mssql && npm run test-unit-sqlite && npm run test-unit-snowflake && npm run test-unit-db2", + "test-unit-oracle": "cross-env DIALECT=oracle npm run test-unit", + "test-unit-all": "npm run test-unit-mariadb && npm run test-unit-mysql && npm run test-unit-postgres && npm run test-unit-postgres-native && npm run test-unit-mssql && npm run test-unit-sqlite && npm run test-unit-snowflake && npm run test-unit-db2 && npm run test-unit-oracle", "test-integration-mariadb": "cross-env DIALECT=mariadb npm run test-integration", "test-integration-mysql": "cross-env DIALECT=mysql npm run test-integration", "test-integration-postgres": "cross-env DIALECT=postgres npm run test-integration", @@ -261,6 +283,7 @@ "test-integration-mssql": "cross-env DIALECT=mssql npm run test-integration", "test-integration-db2": "cross-env DIALECT=db2 npm run test-integration", "test-integration-snowflake": "cross-env DIALECT=snowflake npm run test-integration", + "test-integration-oracle": "cross-env LD_LIBRARY_PATH=\"$PWD/.oracle/instantclient/\" DIALECT=oracle UV_THREADPOOL_SIZE=128 npm run test-integration", "test-mariadb": "cross-env DIALECT=mariadb npm test", "test-mysql": "cross-env DIALECT=mysql npm test", "test-sqlite": "cross-env DIALECT=sqlite npm test", @@ -268,6 +291,7 @@ "test-postgres-native": "cross-env DIALECT=postgres-native npm test", "test-mssql": "cross-env DIALECT=mssql npm test", "test-db2": "cross-env DIALECT=db2 npm test", + "test-oracle": "cross-env LD_LIBRARY_PATH=\"$PWD/.oracle/instantclient/\" DIALECT=oracle UV_THREADPOOL_SIZE=128 npm test", "----------------------------------------- development ---------------------------------------------": "", "sscce": "node sscce.js", "sscce-mariadb": "cross-env DIALECT=mariadb node sscce.js", @@ -277,6 +301,7 @@ "sscce-sqlite": "cross-env DIALECT=sqlite node sscce.js", "sscce-mssql": "cross-env DIALECT=mssql node sscce.js", "sscce-db2": "cross-env DIALECT=db2 node sscce.js", + "sscce-oracle": "cross-env LD_LIBRARY_PATH=\"$PWD/.oracle/instantclient/\" DIALECT=oracle UV_THREADPOOL_SIZE=128 node sscce.js", "prepare": "npm run build && husky install", "build": "node ./build.js", "---------------------------------------------------------------------------------------------------": "" diff --git a/src/data-types.js b/src/data-types.js index 371652be60f9..f75ee2124ba7 100644 --- a/src/data-types.js +++ b/src/data-types.js @@ -211,7 +211,7 @@ class NUMBER extends ABSTRACT { return true; } _stringify(number) { - if (typeof number === 'number' || typeof number === 'boolean' || number === null || number === undefined) { + if (typeof number === 'number' || typeof number === 'bigint' || typeof number === 'boolean' || number === null || number === undefined) { return number; } if (typeof number.toString === 'function') { @@ -1060,6 +1060,7 @@ dialectMap.sqlite = require('./dialects/sqlite/data-types')(DataTypes); dialectMap.mssql = require('./dialects/mssql/data-types')(DataTypes); dialectMap.db2 = require('./dialects/db2/data-types')(DataTypes); dialectMap.snowflake = require('./dialects/snowflake/data-types')(DataTypes); +dialectMap.oracle = require('./dialects/oracle/data-types')(DataTypes); const dialectList = Object.values(dialectMap); diff --git a/src/dialects/abstract/connection-manager.d.ts b/src/dialects/abstract/connection-manager.d.ts index 8bb7674918b9..b3b0907a033d 100644 --- a/src/dialects/abstract/connection-manager.d.ts +++ b/src/dialects/abstract/connection-manager.d.ts @@ -28,7 +28,12 @@ export interface ConnectionManager { */ getConnection(opts: GetConnectionOptions): Promise; /** - * Release a pooled connection so it can be utilized by other connection requests + * Release a pooled connection, so it can be utilized by other connection requests */ - releaseConnection(conn: Connection): Promise; + releaseConnection(conn: Connection): void; + + /** + * Destroys a pooled connection and removes it from the pool. + */ + destroyConnection(conn: Connection): Promise; } diff --git a/src/dialects/abstract/connection-manager.js b/src/dialects/abstract/connection-manager.js index 8f6ee9f44f99..5d58ea134938 100644 --- a/src/dialects/abstract/connection-manager.js +++ b/src/dialects/abstract/connection-manager.js @@ -283,7 +283,13 @@ class ConnectionManager { let result; try { + + await this.sequelize.runHooks('beforePoolAcquire', options); + result = await this.pool.acquire(options.type, options.useMaster); + + await this.sequelize.runHooks('afterPoolAcquire', result, options); + } catch (error) { if (error instanceof TimeoutError) throw new errors.ConnectionAcquireTimeoutError(error); throw error; @@ -298,14 +304,22 @@ class ConnectionManager { * Release a pooled connection so it can be utilized by other connection requests * * @param {Connection} connection - * - * @returns {Promise} */ - async releaseConnection(connection) { + releaseConnection(connection) { this.pool.release(connection); debug('connection released'); } + /** + * Destroys a pooled connection and removes it from the pool. + * + * @param {Connection} connection + */ + async destroyConnection(connection) { + await this.pool.destroy(connection); + debug(`connection ${connection.uuid} destroyed`); + } + /** * Call dialect library to get connection * diff --git a/src/dialects/abstract/index.d.ts b/src/dialects/abstract/index.d.ts index 018463fec091..878efebb83d3 100644 --- a/src/dialects/abstract/index.d.ts +++ b/src/dialects/abstract/index.d.ts @@ -41,6 +41,7 @@ export declare type DialectSupports = { ignoreDuplicates: string; updateOnDuplicate: boolean | string; onConflictDoNothing: string; + onConflictWhere: boolean, conflictFields: boolean; }; constraints: { @@ -85,6 +86,7 @@ export declare type DialectSupports = { tmpTableTrigger: boolean; indexHints: boolean; searchPath: boolean; + escapeStringConstants: boolean; }; export declare abstract class AbstractDialect { @@ -103,4 +105,5 @@ export declare abstract class AbstractDialect { readonly TICK_CHAR_RIGHT: string; readonly queryGenerator: unknown; get supports(): DialectSupports; + canBackslashEscape(): boolean; } diff --git a/src/dialects/abstract/index.js b/src/dialects/abstract/index.js index 5d2c13808166..e2d715695de0 100644 --- a/src/dialects/abstract/index.js +++ b/src/dialects/abstract/index.js @@ -1,6 +1,15 @@ 'use strict'; -class AbstractDialect {} +class AbstractDialect { + /** + * Whether this dialect can use \ in strings to escape string delimiters. + * + * @returns {boolean} + */ + canBackslashEscape() { + return false; + } +} AbstractDialect.prototype.supports = { 'DEFAULT': true, @@ -41,6 +50,7 @@ AbstractDialect.prototype.supports = { ignoreDuplicates: '', /* dialect specific words for INSERT IGNORE or DO NOTHING */ updateOnDuplicate: false, /* whether dialect supports ON DUPLICATE KEY UPDATE */ onConflictDoNothing: '', /* dialect specific words for ON CONFLICT DO NOTHING */ + onConflictWhere: false, /* whether dialect supports ON CONFLICT WHERE */ conflictFields: false /* whether the dialect supports specifying conflict fields or not */ }, constraints: { @@ -66,7 +76,12 @@ AbstractDialect.prototype.supports = { groupedLimit: true, indexViaAlter: false, JSON: false, - deferrableConstraints: false + /** + * This dialect supports marking a column's constraints as deferrable. + * e.g. 'DEFERRABLE' and 'INITIALLY DEFERRED' + */ + deferrableConstraints: false, + escapeStringConstants: false }; module.exports = AbstractDialect; diff --git a/src/dialects/abstract/query-generator.js b/src/dialects/abstract/query-generator.js index b962f3ec7aa5..56f777090018 100644 --- a/src/dialects/abstract/query-generator.js +++ b/src/dialects/abstract/query-generator.js @@ -17,6 +17,35 @@ const Op = require('../../operators'); const sequelizeError = require('../../errors'); const IndexHints = require('../../index-hints'); +/** + * Whitelist of SQL data types allowed in JSON key cast notation (e.g. "key::integer"). + * This prevents SQL injection via user-controlled cast types in _traverseJSON. + * Includes types produced by _getJsonCast() and types transformed by dialect overrides. + */ +const ALLOWED_CAST_TYPES = new Set([ + 'integer', + 'int', + 'smallint', + 'bigint', + 'float', + 'real', + 'double precision', + 'decimal', + 'numeric', + 'boolean', + 'text', + 'char', + 'varchar', + 'nvarchar', + 'date', + 'timestamp', + 'timestamptz', + 'datetime', + 'json', + 'jsonb', + 'signed', + 'unsigned' +]); /** * Abstract Query Generator @@ -43,7 +72,7 @@ class QueryGenerator { options = options || {}; tableName = tableName || {}; return { - schema: tableName.schema || options.schema || 'public', + schema: tableName.schema || options.schema || this.options.schema || 'public', tableName: _.isPlainObject(tableName) ? tableName.tableName : tableName, delimiter: tableName.delimiter || options.delimiter || '.' }; @@ -88,6 +117,16 @@ class QueryGenerator { return `ALTER TABLE ${this.quoteTable(before)} RENAME TO ${this.quoteTable(after)};`; } + /** + * Helper method for populating the returning into bind information + * that is needed by some dialects (currently Oracle) + * + * @private + */ + populateInsertQueryReturnIntoBinds() { + // noop by default + } + /** * Returns an insert into command * @@ -103,12 +142,14 @@ class QueryGenerator { _.defaults(options, this.options); const modelAttributeMap = {}; - const bind = []; + const bind = options.bind || []; const fields = []; const returningModelAttributes = []; + const returnTypes = []; const values = []; const quotedTable = this.quoteTable(table); const bindParam = options.bindParam === undefined ? this.bindParam(bind) : options.bindParam; + const returnAttributes = []; let query; let valueQuery = ''; let emptyQuery = ''; @@ -132,10 +173,14 @@ class QueryGenerator { emptyQuery += ' VALUES ()'; } - if (this._dialect.supports.returnValues && options.returning) { + if ((this._dialect.supports.returnValues || this._dialect.supports.returnIntoValues) && options.returning) { const returnValues = this.generateReturnValues(modelAttributes, options); returningModelAttributes.push(...returnValues.returnFields); + // Storing the returnTypes for dialects that need to have returning into bind information for outbinds + if (this._dialect.supports.returnIntoValues) { + returnTypes.push(...returnValues.returnTypes); + } returningFragment = returnValues.returningFragment; tmpTable = returnValues.tmpTable || ''; outputFragment = returnValues.outputFragment || ''; @@ -182,6 +227,13 @@ class QueryGenerator { let onDuplicateKeyUpdate = ''; + if ( + !_.isEmpty(options.conflictWhere) + && !this._dialect.supports.inserts.onConflictWhere + ) { + throw new Error('missing dialect support for conflictWhere option'); + } + // `options.updateOnDuplicate` is the list of field names to update if a duplicate key is hit during the insert. It // contains just the field names. This option is _usually_ explicitly set by the corresponding query-interface // upsert function. @@ -190,10 +242,28 @@ class QueryGenerator { // If no conflict target columns were specified, use the primary key names from options.upsertKeys const conflictKeys = options.upsertKeys.map(attr => this.quoteIdentifier(attr)); const updateKeys = options.updateOnDuplicate.map(attr => `${this.quoteIdentifier(attr)}=EXCLUDED.${this.quoteIdentifier(attr)}`); - onDuplicateKeyUpdate = ` ON CONFLICT (${conflictKeys.join(',')})`; + + const fragments = [ + 'ON CONFLICT', + '(', + conflictKeys.join(','), + ')' + ]; + + if (!_.isEmpty(options.conflictWhere)) { + fragments.push(this.whereQuery(options.conflictWhere, options)); + } + // if update keys are provided, then apply them here. if there are no updateKeys provided, then do not try to // do an update. Instead, fall back to DO NOTHING. - onDuplicateKeyUpdate += _.isEmpty(updateKeys) ? ' DO NOTHING ' : ` DO UPDATE SET ${updateKeys.join(',')}`; + if (_.isEmpty(updateKeys)) { + fragments.push('DO NOTHING'); + } else { + fragments.push('DO UPDATE SET', updateKeys.join(',')); + } + + onDuplicateKeyUpdate = ` ${Utils.joinSQLFragments(fragments)}`; + } else { const valueKeys = options.updateOnDuplicate.map(attr => `${this.quoteIdentifier(attr)}=VALUES(${this.quoteIdentifier(attr)})`); // the rough equivalent to ON CONFLICT DO NOTHING in mysql, etc is ON DUPLICATE KEY UPDATE id = id @@ -244,7 +314,12 @@ class QueryGenerator { emptyQuery += returningFragment; } - query = `${replacements.attributes.length ? valueQuery : emptyQuery};`; + if (this._dialect.supports.returnIntoValues && options.returning) { + // Populating the returnAttributes array and performing operations needed for output binds of insertQuery + this.populateInsertQueryReturnIntoBinds(returningModelAttributes, returnTypes, bind.length, returnAttributes, options); + } + + query = `${replacements.attributes.length ? valueQuery : emptyQuery}${returnAttributes.join(',')};`; if (this._dialect.supports.finalTable) { query = `SELECT * FROM FINAL TABLE(${ replacements.attributes.length ? valueQuery : emptyQuery });`; } @@ -318,8 +393,31 @@ class QueryGenerator { // If no conflict target columns were specified, use the primary key names from options.upsertKeys const conflictKeys = options.upsertKeys.map(attr => this.quoteIdentifier(attr)); const updateKeys = options.updateOnDuplicate.map(attr => `${this.quoteIdentifier(attr)}=EXCLUDED.${this.quoteIdentifier(attr)}`); - onDuplicateKeyUpdate = ` ON CONFLICT (${conflictKeys.join(',')}) DO UPDATE SET ${updateKeys.join(',')}`; + + let whereClause = false; + if (options.conflictWhere) { + if (!this._dialect.supports.inserts.onConflictWhere) { + throw new Error(`conflictWhere not supported for dialect ${this._dialect.name}`); + } + + whereClause = this.whereQuery(options.conflictWhere, options); + } + + // The Utils.joinSQLFragments later on will join this as it handles nested arrays. + onDuplicateKeyUpdate = [ + 'ON CONFLICT', + '(', + conflictKeys.join(','), + ')', + whereClause, + 'DO UPDATE SET', + updateKeys.join(',') + ]; } else { // mysql / maria + if (options.conflictWhere) { + throw new Error(`conflictWhere not supported for dialect ${this._dialect.name}`); + } + const valueKeys = options.updateOnDuplicate.map(attr => `${this.quoteIdentifier(attr)}=VALUES(${this.quoteIdentifier(attr)})`); onDuplicateKeyUpdate = `${this._dialect.supports.inserts.updateOnDuplicate} ${valueKeys.join(',')}`; } @@ -383,8 +481,18 @@ class QueryGenerator { const bindParam = options.bindParam === undefined ? this.bindParam(bind) : options.bindParam; if (this._dialect.supports['LIMIT ON UPDATE'] && options.limit) { - if (this.dialect !== 'mssql' && this.dialect !== 'db2') { + if (!['mssql', 'db2', 'oracle'].includes(this.dialect)) { suffix = ` LIMIT ${this.escape(options.limit)} `; + } else if (this.dialect === 'oracle') { + // This cannot be setted in where because rownum will be quoted + if (where && (where.length && where.length > 0 || Object.keys(where).length > 0)) { + // If we have a where clause, we add AND + suffix += ' AND '; + } else { + // No where clause, we add where + suffix += ' WHERE '; + } + suffix += `rownum <= ${this.escape(options.limit)} `; } } @@ -939,8 +1047,8 @@ class QueryGenerator { /** * Split a list of identifiers by "." and quote each part. * - * @param {string} identifiers - * + * @param {string} identifiers + * * @returns {string} */ quoteIdentifiers(identifiers) { @@ -963,6 +1071,15 @@ class QueryGenerator { return this.quoteIdentifiers(attribute); } + /** + * Returns the alias token + * + * @returns {string} + */ + getAliasToken() { + return 'AS'; + } + /** * Quote table name with optional alias and schema attribution * @@ -998,7 +1115,7 @@ class QueryGenerator { } if (alias) { - table += ` AS ${this.quoteIdentifier(alias)}`; + table += ` ${this.getAliasToken()} ${this.quoteIdentifier(alias)}`; } return table; @@ -1016,6 +1133,12 @@ class QueryGenerator { return this.handleSequelizeMethod(value); } if (field && field.type) { + if (field.type instanceof DataTypes.STRING + && ['mysql', 'mariadb'].includes(this.dialect) + && ['number', 'boolean'].includes(typeof value)) { + value = String(Number(value)); + } + this.validate(value, field, options); if (field.type.stringify) { @@ -1312,7 +1435,12 @@ class QueryGenerator { } else { // Ordering is handled by the subqueries, so ordering the UNION'ed result is not needed groupedLimitOrder = options.order; - delete options.order; + + // For the Oracle dialect, the result of a select is a set, not a sequence, and so is the result of UNION. + // So the top level ORDER BY is required + if (!this._dialect.supports.topLevelOrderByRequired) { + delete options.order; + } where[Op.placeholder] = true; } @@ -1332,7 +1460,7 @@ class QueryGenerator { model }, model - ).replace(/;$/, '')}) AS sub`; // Every derived table must have its own alias + ).replace(/;$/, '')}) ${this.getAliasToken()} sub`; // Every derived table must have its own alias const placeHolder = this.whereItemQuery(Op.placeholder, true, { model }); const splicePos = baseQuery.indexOf(placeHolder); @@ -1426,7 +1554,7 @@ class QueryGenerator { if (subQuery) { this._throwOnEmptyAttributes(attributes.main, { modelName: model && model.name, as: mainTable.as }); - query = `SELECT ${attributes.main.join(', ')} FROM (${subQueryItems.join('')}) AS ${mainTable.as}${mainJoinQueries.join('')}${mainQueryItems.join('')}`; + query = `SELECT ${attributes.main.join(', ')} FROM (${subQueryItems.join('')}) ${this.getAliasToken()} ${mainTable.as}${mainJoinQueries.join('')}${mainQueryItems.join('')}`; } else { query = mainQueryItems.join(''); } @@ -1476,11 +1604,24 @@ class QueryGenerator { if (attr[0] instanceof Utils.SequelizeMethod) { attr[0] = this.handleSequelizeMethod(attr[0]); addTable = false; - } else if (!attr[0].includes('(') && !attr[0].includes(')')) { + } else if (this.options.attributeBehavior === 'escape' || !attr[0].includes('(') && !attr[0].includes(')')) { attr[0] = this.quoteIdentifier(attr[0]); - } else { - deprecations.noRawAttributes(); + } else if (this.options.attributeBehavior !== 'unsafe-legacy') { + throw new Error(`Attributes cannot include parentheses in Sequelize 6: +In order to fix the vulnerability CVE-2023-22578, we had to remove support for treating attributes as raw SQL if they included parentheses. +Sequelize 7 escapes all attributes, even if they include parentheses. +For Sequelize 6, because we're introducing this change in a minor release, we've opted for throwing an error instead of silently escaping the attribute as a way to warn you about this change. + +Here is what you can do to fix this error: +- Wrap the attribute in a literal() call. This will make Sequelize treat it as raw SQL. +- Set the "attributeBehavior" sequelize option to "escape" to make Sequelize escape the attribute, like in Sequelize v7. We highly recommend this option. +- Set the "attributeBehavior" sequelize option to "unsafe-legacy" to make Sequelize escape the attribute, like in Sequelize v5. + +We sincerely apologize for the inconvenience this may cause you. You can find more information on the following threads: +https://github.com/sequelize/sequelize/security/advisories/GHSA-f598-mfpv-gmfx +https://github.com/sequelize/sequelize/discussions/15694`); } + let alias = attr[1]; if (this.options.minifyAliases) { @@ -1566,6 +1707,8 @@ class QueryGenerator { prefix = `(${this.quoteIdentifier(includeAs.internalAs)}.${attr.replace(/\(|\)/g, '')})`; } else if (/json_extract\(/.test(attr)) { prefix = attr.replace(/json_extract\(/i, `json_extract(${this.quoteIdentifier(includeAs.internalAs)}.`); + } else if (/json_value\(/.test(attr)) { + prefix = attr.replace(/json_value\(/i, `json_value(${this.quoteIdentifier(includeAs.internalAs)}.`); } else { prefix = `${this.quoteIdentifier(includeAs.internalAs)}.${this.quoteIdentifier(attr)}`; } @@ -1773,11 +1916,7 @@ class QueryGenerator { } } - if (this.options.minifyAliases && asRight.length > 63) { - const alias = `%${topLevelInfo.options.includeAliases.size}`; - - topLevelInfo.options.includeAliases.set(alias, asRight); - } + this.aliasAs(asRight, topLevelInfo); return { join: include.required ? 'INNER JOIN' : include.right && this._dialect.supports['RIGHT JOIN'] ? 'RIGHT OUTER JOIN' : 'LEFT OUTER JOIN', @@ -1822,6 +1961,8 @@ class QueryGenerator { if (this._dialect.supports.returnValues.returning) { returningFragment = ` RETURNING ${returnFields.join(',')}`; + } else if (this._dialect.supports.returnIntoValues) { + returningFragment = ` RETURNING ${returnFields.join(',')} INTO `; } else if (this._dialect.supports.returnValues.output) { outputFragment = ` OUTPUT ${returnFields.map(field => `INSERTED.${field}`).join(',')}`; @@ -1835,7 +1976,7 @@ class QueryGenerator { } } - return { outputFragment, returnFields, returningFragment, tmpTable }; + return { outputFragment, returnFields, returnTypes, returningFragment, tmpTable }; } generateThroughJoin(include, includeAs, parentTableName, topLevelInfo) { @@ -1917,6 +2058,8 @@ class QueryGenerator { throughWhere = this.getWhereConditions(through.where, this.sequelize.literal(this.quoteIdentifier(throughAs)), through.model); } + this.aliasAs(includeAs.internalAs, topLevelInfo); + // Generate a wrapped join so that the through table join can be dependent on the target join joinBody = `( ${this.quoteTable(throughTable, throughAs)} INNER JOIN ${this.quoteTable(include.model.getTableName(), includeAs.internalAs)} ON ${targetJoinOn}`; if (throughWhere) { @@ -1944,6 +2087,18 @@ class QueryGenerator { }; } + /* + * Appends to the alias cache if the alias 64+ characters long and minifyAliases is true. + * This helps to avoid character limits in PostgreSQL. + */ + aliasAs(as, topLevelInfo) { + if (this.options.minifyAliases && as.length >= 64) { + const alias = `%${topLevelInfo.options.includeAliases.size}`; + + topLevelInfo.options.includeAliases.set(alias, as); + } + } + /* * Generates subQueryFilter - a select nested in the where clause of the subQuery. * For a given include a query is generated that contains all the way from the subQuery @@ -2083,17 +2238,39 @@ class QueryGenerator { && !(typeof order[0].model === 'function' && order[0].model.prototype instanceof Model) && !(typeof order[0] === 'string' && model && model.associations !== undefined && model.associations[order[0]]) ) { - subQueryOrder.push(this.quote(order, model, '->')); + const field = model.rawAttributes[order[0]] ? model.rawAttributes[order[0]].field : order[0]; + const subQueryAlias = this._getAliasForField(this.quoteIdentifier(model.name), field, options); + + let parent = null; + let orderToQuote = []; + + // we need to ensure that the parent is null if we use the subquery alias, else we'll get an exception since + // "model_name"."alias" doesn't exist - only "alias" does. we also need to ensure that we preserve order direction + // by pushing order[1] to the subQueryOrder as well - in case it doesn't exist, we want to push "ASC" + if (subQueryAlias === null) { + orderToQuote = order; + parent = model; + } else { + orderToQuote = [subQueryAlias, order.length > 1 ? order[1] : 'ASC']; + parent = null; + } + + subQueryOrder.push(this.quote(orderToQuote, parent, '->')); } - if (subQuery) { - // Handle case where sub-query renames attribute we want to order by, - // see https://github.com/sequelize/sequelize/issues/8739 - const subQueryAttribute = options.attributes.find(a => Array.isArray(a) && a[0] === order[0] && a[1]); - if (subQueryAttribute) { + // Handle case where renamed attributes are used to order by, + // see https://github.com/sequelize/sequelize/issues/8739 + // need to check if either of the attribute options match the order + if (options.attributes && model) { + const aliasedAttribute = options.attributes.find(attr => Array.isArray(attr) + && attr[1] + && (attr[0] === order[0] || attr[1] === order[0])); + + if (aliasedAttribute) { const modelName = this.quoteIdentifier(model.name); + const alias = this._getAliasForField(modelName, aliasedAttribute[1], options); - order[0] = new Utils.Col(this._getAliasForField(modelName, subQueryAttribute[1], options) || subQueryAttribute[1]); + order[0] = new Utils.Col(alias || aliasedAttribute[1]); } } @@ -2126,7 +2303,7 @@ class QueryGenerator { let fragment = `SELECT ${attributes.join(', ')} FROM ${tables}`; if (mainTableAs) { - fragment += ` AS ${mainTableAs}`; + fragment += ` ${this.getAliasToken()} ${mainTableAs}`; } if (options.indexHints && this._dialect.supports.indexHints) { @@ -2243,7 +2420,7 @@ class QueryGenerator { if (_.isPlainObject(arg)) { return this.whereItemsQuery(arg); } - return this.escape(typeof arg === 'string' ? arg.replace('$', '$$$') : arg); + return this.escape(typeof arg === 'string' ? arg.replace(/\$/g, '$$$') : arg); }).join(', ') })`; } @@ -2491,6 +2668,8 @@ class QueryGenerator { const tmp = path[path.length - 1].split('::'); cast = tmp[1]; path[path.length - 1] = tmp[0]; + + this._validateCastType(cast); } let pathKey = this.jsonPathExtractionQuery(baseKey, path); @@ -2547,6 +2726,12 @@ class QueryGenerator { return; } + _validateCastType(cast) { + if (!ALLOWED_CAST_TYPES.has(cast.toLowerCase())) { + throw new Error(`Invalid cast type: ${cast}`); + } + } + _joinKeyValue(key, value, comparator, prefix) { if (!key) { return value; @@ -2721,7 +2906,7 @@ class QueryGenerator { type: options.type }); } - if (typeof smth === 'number') { + if (typeof smth === 'number' || typeof smth === 'bigint') { let primaryKeys = factory ? Object.keys(factory.primaryKeys) : []; if (primaryKeys.length > 0) { @@ -2755,14 +2940,14 @@ class QueryGenerator { } throw new Error('Support for literal replacements in the `where` object has been removed.'); } - if (smth === null) { + if (smth == null) { return this.whereItemsQuery(smth, { model: factory, prefix: prepend && tableName }); } - return '1=1'; + throw new Error(`Unsupported where option value: ${util.inspect(smth)}. Please refer to the Sequelize documentation to learn more about which values are accepted as part of the where option.`); } // A recursive parser for nested where conditions @@ -2780,6 +2965,13 @@ class QueryGenerator { booleanValue(value) { return value; } + + /** + * Returns the authenticate test query string + */ + authTestQuery() { + return 'SELECT 1+1 AS result'; + } } Object.assign(QueryGenerator.prototype, require('./query-generator/operators')); diff --git a/src/dialects/abstract/query-interface.d.ts b/src/dialects/abstract/query-interface.d.ts index 782ee8288992..dafa19cac579 100644 --- a/src/dialects/abstract/query-interface.d.ts +++ b/src/dialects/abstract/query-interface.d.ts @@ -377,6 +377,14 @@ export class QueryInterface { */ public showAllTables(options?: QueryOptions): Promise; + /** + * Returns a promise that resolves to true if the table exists in the database, false otherwise. + * + * @param tableName The name of the table + * @param options Options passed to {@link Sequelize#query} + */ + public tableExists(tableName: TableName, options?: QueryOptions): Promise; + /** * Describe a table */ @@ -648,11 +656,6 @@ export class QueryInterface { */ public quoteIdentifiers(identifiers: string): string; - /** - * Escape a value (e.g. a string, number or date) - */ - public escape(value?: string | number | Date): string; - /** * Set option for autocommit of a transaction */ diff --git a/src/dialects/abstract/query-interface.js b/src/dialects/abstract/query-interface.js index 890d79826d17..ac5926bc8b22 100644 --- a/src/dialects/abstract/query-interface.js +++ b/src/dialects/abstract/query-interface.js @@ -219,12 +219,34 @@ class QueryInterface { }); } - attributes = this.queryGenerator.attributesToSQL(attributes, { table: tableName, context: 'createTable' }); + attributes = this.queryGenerator.attributesToSQL(attributes, { + table: tableName, + context: 'createTable', + withoutForeignKeyConstraints: options.withoutForeignKeyConstraints + }); sql = this.queryGenerator.createTableQuery(tableName, attributes, options); return await this.sequelize.query(sql, options); } + /** + * Returns a promise that will resolve to true if the table exists in the database, false otherwise. + * + * @param {TableName} tableName - The name of the table + * @param {QueryOptions} options - Query options + * @returns {Promise} + */ + async tableExists(tableName, options) { + const sql = this.queryGenerator.tableExistsQuery(tableName); + + const out = await this.sequelize.query(sql, { + ...options, + type: QueryTypes.SHOWTABLES + }); + + return out.length === 1; + } + /** * Drop a table from database * @@ -901,7 +923,7 @@ class QueryInterface { const sql = this.queryGenerator.updateQuery(tableName, values, identifier, options, attributes); const table = _.isObject(tableName) ? tableName : { tableName }; - const model = _.find(this.sequelize.modelManager.models, { tableName: table.tableName }); + const model = options.model ? options.model : _.find(this.sequelize.modelManager.models, { tableName: table.tableName }); options.type = QueryTypes.BULKUPDATE; options.model = model; diff --git a/src/dialects/abstract/query.js b/src/dialects/abstract/query.js index 5e141c66a582..8f8b2d598850 100644 --- a/src/dialects/abstract/query.js +++ b/src/dialects/abstract/query.js @@ -550,7 +550,7 @@ class AbstractQuery { // Keys are the same for all rows, so only need to compute them on the first row if (rowsI === 0) { - keys = Object.keys(row); + keys = _.sortBy(Object.keys(row), item => [item.split('.').length]); keyLength = keys.length; } diff --git a/src/dialects/db2/query-generator.js b/src/dialects/db2/query-generator.js index a43f48acb599..4ac3735d33ce 100644 --- a/src/dialects/db2/query-generator.js +++ b/src/dialects/db2/query-generator.js @@ -175,6 +175,16 @@ class Db2QueryGenerator extends AbstractQueryGenerator { return "SELECT TABNAME AS \"tableName\", TRIM(TABSCHEMA) AS \"tableSchema\" FROM SYSCAT.TABLES WHERE TABSCHEMA = USER AND TYPE = 'T' ORDER BY TABSCHEMA, TABNAME"; } + tableExistsQuery(table) { + const tableName = table.tableName || table; + // The default schema is the authorization ID of the owner of the plan or package. + // https://www.ibm.com/docs/en/db2-for-zos/12?topic=concepts-db2-schemas-schema-qualifiers + const schemaName = table.schema || this.sequelize.config.username.toUpperCase(); + + // https://www.ibm.com/docs/en/db2-for-zos/11?topic=tables-systables + return `SELECT name FROM sysibm.systables WHERE NAME = ${wrapSingleQuote(tableName)} AND CREATOR = ${wrapSingleQuote(schemaName)}`; + } + dropTableQuery(tableName) { const query = 'DROP TABLE <%= table %>'; const values = { @@ -621,7 +631,7 @@ class Db2QueryGenerator extends AbstractQueryGenerator { template += ' PRIMARY KEY'; } - if (attribute.references) { + if ((!options || !options.withoutForeignKeyConstraints) && attribute.references) { if (options && options.context === 'addColumn' && options.foreignKey) { const attrName = this.quoteIdentifier(options.foreignKey); const fkName = `${options.tableName }_${ attrName }_fidx`; diff --git a/src/dialects/db2/query-interface.js b/src/dialects/db2/query-interface.js index f310ccc9bed0..535bc4bec27c 100644 --- a/src/dialects/db2/query-interface.js +++ b/src/dialects/db2/query-interface.js @@ -133,7 +133,7 @@ class Db2QueryInterface extends QueryInterface { }); } - attributes = this.queryGenerator.attributesToSQL(attributes, { table: tableName, context: 'createTable' }); + attributes = this.queryGenerator.attributesToSQL(attributes, { table: tableName, context: 'createTable', withoutForeignKeyConstraints: options.withoutForeignKeyConstraints }); sql = this.queryGenerator.createTableQuery(tableName, attributes, options); return await this.sequelize.query(sql, options); diff --git a/src/dialects/db2/query.js b/src/dialects/db2/query.js index 9c6ffe32644d..831419238aaf 100644 --- a/src/dialects/db2/query.js +++ b/src/dialects/db2/query.js @@ -1,5 +1,7 @@ 'use strict'; +const util = require('util'); + const AbstractQuery = require('../abstract/query'); const sequelizeErrors = require('../../errors'); const parserStore = require('../parserStore')('db2'); @@ -14,15 +16,19 @@ class Query extends AbstractQuery { } getSQLTypeFromJsType(value) { - const param = { ParamType: 'INPUT', Data: value }; if (Buffer.isBuffer(value)) { - param.DataType = 'BLOB'; - return param; + return { ParamType: 'INPUT', DataType: 'BLOB', Data: value }; + } + + if (typeof value === 'bigint') { + // The ibm_db module does not handle bigint, send as a string instead: + return value.toString(); } + return value; } - async _run(connection, sql, parameters) { + async _run(connection, sql, parameters) { this.sql = sql; const benchmark = this.sequelize.options.benchmark || this.options.benchmark; let queryBegin; @@ -98,10 +104,10 @@ class Query extends AbstractQuery { } stmt.execute(params, (err, result, outparams) => { - debug(`executed(${this.connection.uuid || 'default'}):${newSql} ${parameters ? JSON.stringify(parameters) : ''}`); + debug(`executed(${this.connection.uuid || 'default'}):${newSql} ${parameters ? util.inspect(parameters, { compact: true, breakLength: Infinity }) : ''}`); if (benchmark) { - this.sequelize.log(`Executed (${ this.connection.uuid || 'default' }): ${ newSql} ${parameters ? JSON.stringify(parameters) : ''}`, Date.now() - queryBegin, this.options); + this.sequelize.log(`Executed (${this.connection.uuid || 'default'}): ${newSql} ${parameters ? util.inspect(parameters, { compact: true, breakLength: Infinity }) : ''}`, Date.now() - queryBegin, this.options); } if (err && err.message) { @@ -454,7 +460,7 @@ class Query extends AbstractQuery { result = result || this.sql.startsWith('SELECT NAME AS "name", TBNAME AS "tableName", UNIQUERULE AS "keyType", COLNAMES, INDEXTYPE AS "type" FROM SYSIBM.SYSINDEXES'); return result; } - + handleShowIndexesQuery(data) { let currItem; const result = []; @@ -468,7 +474,7 @@ class Query extends AbstractQuery { unique: item.keyType === 'U', type: item.type }; - + _.forEach(item.COLNAMES.replace(/\+|-/g, x => { return ` ${ x}`; }).split(' '), column => { let columnName = column.trim(); if ( columnName ) { @@ -484,7 +490,7 @@ class Query extends AbstractQuery { result.push(currItem); } }); - return result; + return result; } handleInsertQuery(results, metaData) { diff --git a/src/dialects/mariadb/index.js b/src/dialects/mariadb/index.js index e1ff8dfb3224..855c1106cbd4 100644 --- a/src/dialects/mariadb/index.js +++ b/src/dialects/mariadb/index.js @@ -22,6 +22,10 @@ class MariadbDialect extends AbstractDialect { this.queryGenerator ); } + + canBackslashEscape() { + return true; + } } MariadbDialect.prototype.supports = _.merge( diff --git a/src/dialects/mariadb/query.js b/src/dialects/mariadb/query.js index 12d8f9c9d5b3..2f05d444f563 100644 --- a/src/dialects/mariadb/query.js +++ b/src/dialects/mariadb/query.js @@ -129,6 +129,7 @@ class Query extends AbstractQuery { if (this.isSelectQuery()) { this.handleJsonSelectQuery(data); + return this.handleSelectQuery(data); } if (this.isInsertQuery() || this.isUpdateQuery()) { @@ -184,7 +185,9 @@ class Query extends AbstractQuery { if (modelField.type instanceof DataTypes.JSON) { // Value is returned as String, not JSON rows = rows.map(row => { - if (row[modelField.fieldName] && typeof row[modelField.fieldName] === 'string') { + // JSON fields for MariaDB server 10.5.2+ already results in JSON format, skip JSON.parse + // this is due to this https://jira.mariadb.org/browse/MDEV-17832 and how mysql2 connector interacts with MariaDB and JSON fields + if (row[modelField.fieldName] && typeof row[modelField.fieldName] === 'string' && !this.connection.info.hasMinVersion(10, 5, 2)) { row[modelField.fieldName] = JSON.parse(row[modelField.fieldName]); } if (DataTypes.JSON.parse) { diff --git a/src/dialects/mssql/connection-manager.js b/src/dialects/mssql/connection-manager.js index 9d929370c12e..76c2f9f1b63b 100644 --- a/src/dialects/mssql/connection-manager.js +++ b/src/dialects/mssql/connection-manager.js @@ -129,6 +129,9 @@ class ConnectionManager extends AbstractConnectionManager { if (error.message.includes('connect EADDRNOTAVAIL')) { throw new sequelizeErrors.HostNotReachableError(error); } + if (error.message.includes('connect EAFNOSUPPORT')) { + throw new sequelizeErrors.HostNotReachableError(error); + } if (error.message.includes('getaddrinfo ENOTFOUND')) { throw new sequelizeErrors.HostNotFoundError(error); } diff --git a/src/dialects/mssql/query-generator.js b/src/dialects/mssql/query-generator.js index 49d73adec724..edc0a86d557f 100644 --- a/src/dialects/mssql/query-generator.js +++ b/src/dialects/mssql/query-generator.js @@ -192,7 +192,7 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator { "c.IS_NULLABLE as 'IsNull',", "COLUMN_DEFAULT AS 'Default',", "pk.CONSTRAINT_TYPE AS 'Constraint',", - "COLUMNPROPERTY(OBJECT_ID(c.TABLE_SCHEMA+'.'+c.TABLE_NAME), c.COLUMN_NAME, 'IsIdentity') as 'IsIdentity',", + "COLUMNPROPERTY(OBJECT_ID('[' + c.TABLE_SCHEMA + '].[' + c.TABLE_NAME + ']'), c.COLUMN_NAME, 'IsIdentity') as 'IsIdentity',", "CAST(prop.value AS NVARCHAR) AS 'Comment'", 'FROM', 'INFORMATION_SCHEMA.TABLES t', @@ -209,7 +209,7 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator { 'AND pk.table_name=c.table_name ', 'AND pk.column_name=c.column_name ', 'INNER JOIN sys.columns AS sc', - "ON sc.object_id = object_id(t.table_schema + '.' + t.table_name) AND sc.name = c.column_name", + "ON sc.object_id = OBJECT_ID('[' + t.TABLE_SCHEMA + '].[' + t.TABLE_NAME + ']') AND sc.name = c.column_name", 'LEFT JOIN sys.extended_properties prop ON prop.major_id = sc.object_id', 'AND prop.minor_id = sc.column_id', "AND prop.name = 'MS_Description'", @@ -231,6 +231,13 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator { return "SELECT TABLE_NAME, TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE';"; } + tableExistsQuery(table) { + const tableName = table.tableName || table; + const schemaName = table.schema || 'dbo'; + + return `SELECT TABLE_NAME, TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = ${this.escape(tableName)} AND TABLE_SCHEMA = ${this.escape(schemaName)}`; + } + dropTableQuery(tableName) { const quoteTbl = this.quoteTable(tableName); return Utils.joinSQLFragments([ @@ -557,7 +564,7 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator { return `DROP INDEX ${this.quoteIdentifiers(indexName)} ON ${this.quoteIdentifiers(tableName)}`; } - attributeToSQL(attribute) { + attributeToSQL(attribute, options) { if (!_.isPlainObject(attribute)) { attribute = { type: attribute @@ -613,7 +620,7 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator { template += ' PRIMARY KEY'; } - if (attribute.references) { + if ((!options || !options.withoutForeignKeyConstraints) && attribute.references) { template += ` REFERENCES ${this.quoteTable(attribute.references.model)}`; if (attribute.references.key) { @@ -969,12 +976,39 @@ class MSSQLQueryGenerator extends AbstractQueryGenerator { // TODO: document why this is adding the primary key of the model in ORDER BY // if options.include is set if (!options.order || options.order.length === 0 || options.include && orders.subQueryOrder.length === 0) { - const tablePkFragment = `${this.quoteTable(options.tableAs || model.name)}.${this.quoteIdentifier(model.primaryKeyField)}`; + let primaryKey = model.primaryKeyField; + + const tablePkFragment = `${this.quoteTable(options.tableAs || model.name)}.${this.quoteIdentifier(primaryKey)}`; + const aliasedAttribute = (options.attributes || []).find(attr => Array.isArray(attr) + && attr[1] + && (attr[0] === primaryKey || attr[1] === primaryKey)); + + if (aliasedAttribute) { + const modelName = this.quoteIdentifier(options.tableAs || model.name); + const alias = this._getAliasForField(modelName, aliasedAttribute[1], options); + + primaryKey = new Utils.Col(alias || aliasedAttribute[1]); + } + if (!options.order || !options.order.length) { fragment += ` ORDER BY ${tablePkFragment}`; } else { - const orderFieldNames = _.map(options.order, order => order[0]); - const primaryKeyFieldAlreadyPresent = _.includes(orderFieldNames, model.primaryKeyField); + const orderFieldNames = (options.order || []).map(order => { + const value = Array.isArray(order) ? order[0] : order; + + if (value instanceof Utils.Col) { + return value.col; + } + + if (value instanceof Utils.Literal) { + return value.val; + } + + return value; + }); + const primaryKeyFieldAlreadyPresent = orderFieldNames.some( + fieldName => fieldName === (primaryKey.col || primaryKey) + ); if (!primaryKeyFieldAlreadyPresent) { fragment += options.order && !isSubQuery ? ', ' : ' ORDER BY '; diff --git a/src/dialects/mssql/query.js b/src/dialects/mssql/query.js index f35c43d948e7..8145368dc54a 100644 --- a/src/dialects/mssql/query.js +++ b/src/dialects/mssql/query.js @@ -8,6 +8,9 @@ const { logger } = require('../../utils/logger'); const debug = logger.debugContext('sql:mssql'); +const minSafeIntegerAsBigInt = BigInt(Number.MIN_SAFE_INTEGER); +const maxSafeIntegerAsBigInt = BigInt(Number.MAX_SAFE_INTEGER); + function getScale(aNum) { if (!Number.isFinite(aNum)) return 0; let e = 1; @@ -21,8 +24,7 @@ class Query extends AbstractQuery { } getSQLTypeFromJsType(value, TYPES) { - const paramType = { type: TYPES.VarChar, typeOptions: {} }; - paramType.type = TYPES.NVarChar; + const paramType = { type: TYPES.NVarChar, typeOptions: {}, value }; if (typeof value === 'number') { if (Number.isInteger(value)) { if (value >= -2147483648 && value <= 2147483647) { @@ -35,6 +37,13 @@ class Query extends AbstractQuery { //Default to a reasonable numeric precision/scale pending more sophisticated logic paramType.typeOptions = { precision: 30, scale: getScale(value) }; } + } else if (typeof value === 'bigint') { + if (value < minSafeIntegerAsBigInt || value > maxSafeIntegerAsBigInt) { + paramType.type = TYPES.VarChar; + paramType.value = value.toString(); + } else { + return this.getSQLTypeFromJsType(Number(value), TYPES); + } } else if (typeof value === 'boolean') { paramType.type = TYPES.Bit; } diff --git a/src/dialects/mysql/index.js b/src/dialects/mysql/index.js index a9850b11e83b..797706092849 100644 --- a/src/dialects/mysql/index.js +++ b/src/dialects/mysql/index.js @@ -22,6 +22,10 @@ class MysqlDialect extends AbstractDialect { this.queryGenerator ); } + + canBackslashEscape() { + return true; + } } MysqlDialect.prototype.supports = _.merge( diff --git a/src/dialects/mysql/query-generator.js b/src/dialects/mysql/query-generator.js index 9653d076f78e..13c549b5d79f 100644 --- a/src/dialects/mysql/query-generator.js +++ b/src/dialects/mysql/query-generator.js @@ -164,11 +164,18 @@ class MySQLQueryGenerator extends AbstractQueryGenerator { if (database) { query += ` AND TABLE_SCHEMA = ${this.escape(database)}`; } else { - query += ' AND TABLE_SCHEMA NOT IN (\'MYSQL\', \'INFORMATION_SCHEMA\', \'PERFORMANCE_SCHEMA\', \'SYS\')'; + query += ' AND TABLE_SCHEMA NOT IN (\'MYSQL\', \'INFORMATION_SCHEMA\', \'PERFORMANCE_SCHEMA\', \'SYS\', \'mysql\', \'information_schema\', \'performance_schema\', \'sys\')'; } return `${query};`; } + tableExistsQuery(table) { + // remove first & last `, then escape as SQL string + const tableName = this.escape(this.quoteTable(table).slice(1, -1)); + + return `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = ${tableName} AND TABLE_SCHEMA = ${this.escape(this.sequelize.config.database)}`; + } + addColumnQuery(table, key, dataType) { return Utils.joinSQLFragments([ 'ALTER TABLE', @@ -398,7 +405,7 @@ class MySQLQueryGenerator extends AbstractQueryGenerator { template += ` AFTER ${this.quoteIdentifier(attribute.after)}`; } - if (attribute.references) { + if ((!options || !options.withoutForeignKeyConstraints) && attribute.references) { if (options && options.context === 'addColumn' && options.foreignKey) { const attrName = this.quoteIdentifier(options.foreignKey); const fkName = this.quoteIdentifier(`${options.tableName}_${attrName}_foreign_idx`); diff --git a/src/dialects/oracle/connection-manager.js b/src/dialects/oracle/connection-manager.js new file mode 100644 index 000000000000..44e791236304 --- /dev/null +++ b/src/dialects/oracle/connection-manager.js @@ -0,0 +1,179 @@ +// Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +'use strict'; + +const AbstractConnectionManager = require('../abstract/connection-manager'); +const SequelizeErrors = require('../../errors'); +const parserStore = require('../parserStore')('oracle'); +const { logger } = require('../../utils/logger'); +const semver = require('semver'); +const debug = logger.debugContext('connection:oracle'); +const DataTypes = require('../../data-types').oracle; +const { promisify } = require('util'); +/** + * Oracle Connection Manager + * + * Get connections, validate and disconnect them. + * AbstractConnectionManager pooling use it to handle Oracle specific connections + * Use github.com/oracle/node-oracledb to connect with Oracle server + * + * @private + */ +export class OracleConnectionManager extends AbstractConnectionManager { + constructor(dialect, sequelize) { + super(dialect, sequelize); + + this.sequelize = sequelize; + this.sequelize.config.port = this.sequelize.config.port || 1521; + this.lib = this._loadDialectModule('oracledb'); + this.extendLib(); + this.refreshTypeParser(DataTypes); + } + + /** + * Method for initializing the lib + * + */ + extendLib() { + if (this.sequelize.config && 'dialectOptions' in this.sequelize.config) { + const dialectOptions = this.sequelize.config.dialectOptions; + if (dialectOptions && 'maxRows' in dialectOptions) { + this.lib.maxRows = this.sequelize.config.dialectOptions.maxRows; + } + if (dialectOptions && 'fetchAsString' in dialectOptions) { + this.lib.fetchAsString = this.sequelize.config.dialectOptions.fetchAsString; + } else { + this.lib.fetchAsString = [this.lib.CLOB]; + } + } + // Retrieve BLOB always as Buffer. + this.lib.fetchAsBuffer = [this.lib.BLOB]; + } + + /** + * Method for checking the config object passed and generate the full database if not fully passed + * With dbName, host and port, it generates a string like this : 'host:port/dbname' + * + * @param {object} config + * @returns {Promise} + * @private + */ + buildConnectString(config) { + if (!config.host || config.host.length === 0) + return config.database; + let connectString = config.host; + if (config.port && config.port > 0) { + connectString += `:${config.port}`; + } else { + connectString += ':1521'; + } + if (config.database && config.database.length > 0) { + connectString += `/${config.database}`; + } + return connectString; + } + + // Expose this as a method so that the parsing may be updated when the user has added additional, custom types + _refreshTypeParser(dataType) { + parserStore.refresh(dataType); + } + + _clearTypeParser() { + parserStore.clear(); + } + + /** + * Connect with Oracle database based on config, Handle any errors in connection + * Set the pool handlers on connection.error + * Also set proper timezone once connection is connected. + * + * @param {object} config + * @returns {Promise} + * @private + */ + async connect(config) { + const connectionConfig = { + user: config.username, + password: config.password, + externalAuth: config.externalAuth, + stmtCacheSize: 0, + connectString: this.buildConnectString(config), + ...config.dialectOptions + }; + + try { + const connection = await this.lib.getConnection(connectionConfig); + // Setting the sequelize database version to Oracle DB server version to remove the roundtrip for DB version query + this.sequelize.options.databaseVersion = semver.coerce(connection.oracleServerVersionString).version; + + debug('connection acquired'); + connection.on('error', error => { + switch (error.code) { + case 'ESOCKET': + case 'ECONNRESET': + case 'EPIPE': + case 'PROTOCOL_CONNECTION_LOST': + this.pool.destroy(connection); + } + }); + + return connection; + } catch (err) { + // We split to get the error number; it comes as ORA-XXXXX: + let errorCode = err.message.split(':'); + errorCode = errorCode[0]; + + switch (errorCode) { + case 'ORA-12560': // ORA-12560: TNS: Protocol Adapter Error + case 'ORA-12154': // ORA-12154: TNS: Could not resolve the connect identifier specified + case 'ORA-12505': // ORA-12505: TNS: Listener does not currently know of SID given in connect descriptor + case 'ORA-12514': // ORA-12514: TNS: Listener does not currently know of service requested in connect descriptor + case 'NJS-511': // NJS-511: connection refused + case 'NJS-516': // NJS-516: No Config Dir + case 'NJS-517': // NJS-517: TNS Entry not found + case 'NJS-520': // NJS-520: TNS Names File missing + throw new SequelizeErrors.ConnectionRefusedError(err); + case 'ORA-28000': // ORA-28000: Account locked + case 'ORA-28040': // ORA-28040: No matching authentication protocol + case 'ORA-01017': // ORA-01017: invalid username/password; logon denied + case 'NJS-506': // NJS-506: TLS Auth Failure + throw new SequelizeErrors.AccessDeniedError(err); + case 'ORA-12541': // ORA-12541: TNS: No listener + case 'NJS-503': // NJS-503: Connection Incomplete + case 'NJS-508': // NJS-508: TLS HOST MATCH Failure + case 'NJS-507': // NJS-507: TLS DN MATCH Failure + throw new SequelizeErrors.HostNotReachableError(err); + case 'NJS-512': // NJS-512: Invalid Connect String Parameters + case 'NJS-515': // NJS-515: Invalid EZCONNECT Syntax + case 'NJS-518': // NJS-518: Invald ServiceName + case 'NJS-519': // NJS-519: Invald SID + throw new SequelizeErrors.InvalidConnectionError(err); + case 'ORA-12170': // ORA-12170: TNS: Connect Timeout occurred + case 'NJS-510': // NJS-510: Connect Timeout occurred + + throw new SequelizeErrors.ConnectionTimedOutError(err); + default: + throw new SequelizeErrors.ConnectionError(err); + } + } + } + + async disconnect(connection) { + if (!connection.isHealthy()) { + debug('connection tried to disconnect but was already at CLOSED state'); + return; + } + + return await promisify(callback => connection.close(callback))(); + } + + /** + * Checking if the connection object is valid and the connection is healthy + * + * @param {object} connection + * @private + */ + validate(connection) { + return connection && connection.isHealthy(); + } +} diff --git a/src/dialects/oracle/data-types.js b/src/dialects/oracle/data-types.js new file mode 100644 index 000000000000..2bb99a00debc --- /dev/null +++ b/src/dialects/oracle/data-types.js @@ -0,0 +1,486 @@ +// Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +'use strict'; + +const moment = require('moment'); +const momentTz = require('moment-timezone'); + +module.exports = BaseTypes => { + const warn = BaseTypes.ABSTRACT.warn.bind( + undefined, + 'https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-D424D23B-0933-425F-BC69-9C0E6724693C' + ); + + BaseTypes.DATE.types.oracle = ['TIMESTAMP', 'TIMESTAMP WITH LOCAL TIME ZONE']; + BaseTypes.STRING.types.oracle = ['VARCHAR2', 'NVARCHAR2']; + BaseTypes.CHAR.types.oracle = ['CHAR', 'RAW']; + BaseTypes.TEXT.types.oracle = ['CLOB']; + BaseTypes.TINYINT.types.oracle = ['NUMBER']; + BaseTypes.SMALLINT.types.oracle = ['NUMBER']; + BaseTypes.MEDIUMINT.types.oracle = ['NUMBER']; + BaseTypes.INTEGER.types.oracle = ['INTEGER']; + BaseTypes.BIGINT.types.oracle = ['NUMBER']; + BaseTypes.FLOAT.types.oracle = ['BINARY_FLOAT']; + BaseTypes.DATEONLY.types.oracle = ['DATE']; + BaseTypes.BOOLEAN.types.oracle = ['CHAR(1)']; + BaseTypes.BLOB.types.oracle = ['BLOB']; + BaseTypes.DECIMAL.types.oracle = ['NUMBER']; + BaseTypes.UUID.types.oracle = ['VARCHAR2']; + BaseTypes.ENUM.types.oracle = ['VARCHAR2']; + BaseTypes.REAL.types.oracle = ['BINARY_DOUBLE']; + BaseTypes.DOUBLE.types.oracle = ['BINARY_DOUBLE']; + BaseTypes.JSON.types.oracle = ['BLOB']; + BaseTypes.GEOMETRY.types.oracle = false; + + class STRING extends BaseTypes.STRING { + toSql() { + if (this.length > 4000 || this._binary && this._length > 2000) { + warn( + 'Oracle supports length up to 32764 bytes or characters; Be sure that your administrator has extended the MAX_STRING_SIZE parameter. Check https://docs.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-7B72E154-677A-4342-A1EA-C74C1EA928E6' + ); + } + if (!this._binary) { + return `NVARCHAR2(${this._length})`; + } + return `RAW(${this._length})`; + } + + _stringify(value, options) { + if (this._binary) { + // For Binary numbers we're converting a buffer to hex then + // sending it over the wire as a string, + // We pass it through escape function to remove un-necessary quotes + // this.format in insert/bulkinsert query calls stringify hence we need to convert binary buffer + // to hex string. Since this block is used by both bind (insert/bulkinsert) and + // non-bind (select query where clause) hence we need to + // have an operation that supports both + return options.escape(value.toString('hex')); + } + return options.escape(value); + } + + _getBindDef(oracledb) { + if (this._binary) { + return { type: oracledb.DB_TYPE_RAW, maxSize: this._length }; + } + return { type: oracledb.DB_TYPE_VARCHAR, maxSize: this._length }; + } + + _bindParam(value, options) { + return options.bindParam(value); + } + } + + STRING.prototype.escape = false; + + class BOOLEAN extends BaseTypes.BOOLEAN { + toSql() { + return 'CHAR(1)'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_CHAR, maxSize: 1 }; + } + + _stringify(value) { + // If value is true we return '1' + // If value is false we return '0' + // Else we return it as is + // Converting number to char since in bindDef + // the type would be oracledb.DB_TYPE_CHAR + return value === true ? '1' : value === false ? '0' : value; + } + + _sanitize(value) { + if (typeof value === 'string') { + // If value is a string we return true if among '1' and 'true' + // We return false if among '0' and 'false' + // Else return the value as is and let the DB raise error for invalid values + return value === '1' || value === 'true' ? true : value === '0' || value === 'false' ? false : value; + } + return super._sanitize(value); + } + } + + class UUID extends BaseTypes.UUID { + toSql() { + return 'VARCHAR2(36)'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_VARCHAR, maxSize: 36 }; + } + } + + class NOW extends BaseTypes.NOW { + toSql() { + return 'SYSDATE'; + } + + _stringify() { + return 'SYSDATE'; + } + } + + class ENUM extends BaseTypes.ENUM { + toSql() { + return 'VARCHAR2(512)'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_VARCHAR, maxSize: 512 }; + } + } + + class TEXT extends BaseTypes.TEXT { + toSql() { + return 'CLOB'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_CLOB }; + } + } + + class CHAR extends BaseTypes.CHAR { + toSql() { + if (this._binary) { + warn('Oracle CHAR.BINARY datatype is not of Fixed Length.'); + return `RAW(${this._length})`; + } + return super.toSql(); + } + + _getBindDef(oracledb) { + if (this._binary) { + return { type: oracledb.DB_TYPE_RAW, maxSize: this._length }; + } + return { type: oracledb.DB_TYPE_CHAR, maxSize: this._length }; + } + + _bindParam(value, options) { + return options.bindParam(value); + } + } + + class DATE extends BaseTypes.DATE { + toSql() { + return 'TIMESTAMP WITH LOCAL TIME ZONE'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_TIMESTAMP_LTZ }; + } + + _stringify(date, options) { + const format = 'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM'; + + date = this._applyTimezone(date, options); + + const formatedDate = date.format('YYYY-MM-DD HH:mm:ss.SSS Z'); + + return `TO_TIMESTAMP_TZ('${formatedDate}','${format}')`; + } + + _applyTimezone(date, options) { + if (options.timezone) { + if (momentTz.tz.zone(options.timezone)) { + date = momentTz(date).tz(options.timezone); + } else { + date = moment(date).utcOffset(options.timezone); + } + } else { + date = momentTz(date); + } + return date; + } + + static parse(value, options) { + if (value === null) { + return value; + } + if (options && moment.tz.zone(options.timezone)) { + value = moment.tz(value.toString(), options.timezone).toDate(); + } + return value; + } + + /** + * avoids appending TO_TIMESTAMP_TZ in _stringify + * + * @override + */ + _bindParam(value, options) { + return options.bindParam(value); + } + } + + DATE.prototype.escape = false; + + class DECIMAL extends BaseTypes.DECIMAL { + toSql() { + let result = ''; + if (this._length) { + result += `(${this._length}`; + if (typeof this._decimals === 'number') { + result += `,${this._decimals}`; + } + result += ')'; + } + + if (!this._length && this._precision) { + result += `(${this._precision}`; + if (typeof this._scale === 'number') { + result += `,${this._scale}`; + } + result += ')'; + } + + return `NUMBER${result}`; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_NUMBER }; + } + } + + class TINYINT extends BaseTypes.TINYINT { + toSql() { + return 'NUMBER(3)'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_NUMBER }; + } + } + + class SMALLINT extends BaseTypes.SMALLINT { + toSql() { + if (this._length) { + return `NUMBER(${this._length},0)`; + } + return 'SMALLINT'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_NUMBER }; + } + } + + class MEDIUMINT extends BaseTypes.MEDIUMINT { + toSql() { + return 'NUMBER(8)'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_NUMBER }; + } + } + + class BIGINT extends BaseTypes.BIGINT { + constructor(length) { + super(length); + if (!(this instanceof BIGINT)) return new BIGINT(length); + BaseTypes.BIGINT.apply(this, arguments); + + // ORACLE does not support any options for bigint + if (this._length || this.options.length || this._unsigned || this._zerofill) { + warn('Oracle does not support BIGINT with options'); + this._length = undefined; + this.options.length = undefined; + this._unsigned = undefined; + this._zerofill = undefined; + } + } + + toSql() { + return 'NUMBER(19)'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_NUMBER }; + } + + _sanitize(value) { + if (typeof value === 'bigint' || typeof value === 'number') { + return value.toString(); + } + return value; + } + + } + + class NUMBER extends BaseTypes.NUMBER { + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_NUMBER }; + } + } + + class INTEGER extends BaseTypes.INTEGER { + toSql() { + if (this._length) { + return `NUMBER(${this._length},0)`; + } + return 'INTEGER'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_NUMBER }; + } + } + + class FLOAT extends BaseTypes.FLOAT { + toSql() { + return 'BINARY_FLOAT'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_BINARY_FLOAT }; + } + } + + class REAL extends BaseTypes.REAL { + toSql() { + return 'BINARY_DOUBLE'; + } + + // https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-0BA2E065-8006-426C-A3CB-1F6B0C8F283C + _stringify(value) { + if (value === Number.POSITIVE_INFINITY) { + return 'inf'; + } + if (value === Number.NEGATIVE_INFINITY) { + return '-inf'; + } + return value; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_BINARY_DOUBLE }; + } + } + + class BLOB extends BaseTypes.BLOB { + // Generic hexify returns X'${hex}' but Oracle expects '${hex}' for BLOB datatype + _hexify(hex) { + return `'${hex}'`; + } + + toSql() { + return 'BLOB'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_BLOB }; + } + } + + class JSONTYPE extends BaseTypes.JSON { + toSql() { + return 'BLOB'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_BLOB }; + } + + _stringify(value, options) { + return options.operation === 'where' && typeof value === 'string' ? value : JSON.stringify(value); + } + + _bindParam(value, options) { + return options.bindParam(Buffer.from(JSON.stringify(value))); + } + } + + class DOUBLE extends BaseTypes.DOUBLE { + constructor(length, decimals) { + super(length, decimals); + if (!(this instanceof DOUBLE)) return new BaseTypes.DOUBLE(length, decimals); + BaseTypes.DOUBLE.apply(this, arguments); + + if (this._length || this._unsigned || this._zerofill) { + warn('Oracle does not support DOUBLE with options.'); + this._length = undefined; + this.options.length = undefined; + this._unsigned = undefined; + this._zerofill = undefined; + } + + this.key = 'DOUBLE PRECISION'; + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_BINARY_DOUBLE }; + } + + toSql() { + return 'BINARY_DOUBLE'; + } + } + class DATEONLY extends BaseTypes.DATEONLY { + parse(value) { + return moment(value).format('YYYY-MM-DD'); + } + + _sanitize(value) { + if (value) { + return moment(value).format('YYYY-MM-DD'); + } + return value; + } + + _stringify(date, options) { + // If date is not null only then we format the date + if (date) { + const format = 'YYYY/MM/DD'; + return options.escape(`TO_DATE('${date}','${format}')`); + } + return options.escape(date); + } + + _getBindDef(oracledb) { + return { type: oracledb.DB_TYPE_DATE }; + } + + /** + * avoids appending TO_DATE in _stringify + * + * @override + */ + _bindParam(value, options) { + if (typeof value === 'string') { + return options.bindParam(new Date(value)); + } + return options.bindParam(value); + + } + } + + DATEONLY.prototype.escape = false; + + return { + BOOLEAN, + 'DOUBLE PRECISION': DOUBLE, + DOUBLE, + STRING, + TINYINT, + SMALLINT, + MEDIUMINT, + BIGINT, + NUMBER, + INTEGER, + FLOAT, + UUID, + DATEONLY, + DATE, + NOW, + BLOB, + ENUM, + TEXT, + CHAR, + JSON: JSONTYPE, + REAL, + DECIMAL + }; +}; diff --git a/src/dialects/oracle/index.js b/src/dialects/oracle/index.js new file mode 100644 index 000000000000..2e03d9f1585b --- /dev/null +++ b/src/dialects/oracle/index.js @@ -0,0 +1,68 @@ +// Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +'use strict'; + +const _ = require('lodash'); +const { AbstractDialect } = require('../abstract'); +const { OracleConnectionManager } = require('./connection-manager'); +const { OracleQuery } = require('./query'); +const { OracleQueryGenerator } = require('./query-generator'); +const DataTypes = require('../../data-types').oracle; +const { OracleQueryInterface } = require('./query-interface'); + +class OracleDialect extends AbstractDialect { + constructor(sequelize) { + super(); + this.sequelize = sequelize; + this.connectionManager = new OracleConnectionManager(this, sequelize); + this.connectionManager.initPools(); + this.queryGenerator = new OracleQueryGenerator({ + _dialect: this, + sequelize + }); + this.queryInterface = new OracleQueryInterface(sequelize, this.queryGenerator); + } +} + +OracleDialect.prototype.supports = _.merge(_.cloneDeep(AbstractDialect.prototype.supports), { + 'VALUES ()': true, + 'LIMIT ON UPDATE': true, + IGNORE: ' IGNORE', + lock: true, + lockOuterJoinFailure: true, + forShare: 'FOR UPDATE', + skipLocked: true, + index: { + collate: false, + length: false, + parser: false, + type: false, + using: false + }, + constraints: { + restrict: false + }, + returnValues: false, + returnIntoValues: true, + 'ORDER NULLS': true, + schemas: true, + updateOnDuplicate: false, + indexViaAlter: false, + NUMERIC: true, + JSON: true, + upserts: true, + bulkDefault: true, + topLevelOrderByRequired: true, + GEOMETRY: false +}); + +OracleDialect.prototype.defaultVersion = '18.0.0'; +OracleDialect.prototype.Query = OracleQuery; +OracleDialect.prototype.queryGenerator = OracleQueryGenerator; +OracleDialect.prototype.DataTypes = DataTypes; +OracleDialect.prototype.name = 'oracle'; +OracleDialect.prototype.TICK_CHAR = '"'; +OracleDialect.prototype.TICK_CHAR_LEFT = OracleDialect.prototype.TICK_CHAR; +OracleDialect.prototype.TICK_CHAR_RIGHT = OracleDialect.prototype.TICK_CHAR; + +module.exports = OracleDialect; diff --git a/src/dialects/oracle/query-generator.js b/src/dialects/oracle/query-generator.js new file mode 100644 index 000000000000..5a2a56449357 --- /dev/null +++ b/src/dialects/oracle/query-generator.js @@ -0,0 +1,1292 @@ +// Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +'use strict'; + +const Utils = require('../../utils'); +const DataTypes = require('../../data-types'); +const AbstractQueryGenerator = require('../abstract/query-generator'); +const _ = require('lodash'); +const util = require('util'); +const Transaction = require('../../transaction'); + +/** + * list of reserved words in Oracle DB 21c + * source: https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-7B72E154-677A-4342-A1EA-C74C1EA928E6 + * + * @private + */ +const ORACLE_RESERVED_WORDS = ['ACCESS', 'ADD', 'ALL', 'ALTER', 'AND', 'ANY', 'ARRAYLEN', 'AS', 'ASC', 'AUDIT', 'BETWEEN', 'BY', 'CHAR', 'CHECK', 'CLUSTER', 'COLUMN', 'COMMENT', 'COMPRESS', 'CONNECT', 'CREATE', 'CURRENT', 'DATE', 'DECIMAL', 'DEFAULT', 'DELETE', 'DESC', 'DISTINCT', 'DROP', 'ELSE', 'EXCLUSIVE', 'EXISTS', 'FILE', 'FLOAT', 'FOR', 'FROM', 'GRANT', 'GROUP', 'HAVING', 'IDENTIFIED', 'IMMEDIATE', 'IN', 'INCREMENT', 'INDEX', 'INITIAL', 'INSERT', 'INTEGER', 'INTERSECT', 'INTO', 'IS', 'LEVEL', 'LIKE', 'LOCK', 'LONG', 'MAXEXTENTS', 'MINUS', 'MODE', 'MODIFY', 'NOAUDIT', 'NOCOMPRESS', 'NOT', 'NOTFOUND', 'NOWAIT', 'NULL', 'NUMBER', 'OF', 'OFFLINE', 'ON', 'ONLINE', 'OPTION', 'OR', 'ORDER', 'PCTFREE', 'PRIOR', 'PRIVILEGES', 'PUBLIC', 'RAW', 'RENAME', 'RESOURCE', 'REVOKE', 'ROW', 'ROWID', 'ROWLABEL', 'ROWNUM', 'ROWS', 'SELECT', 'SESSION', 'SET', 'SHARE', 'SIZE', 'SMALLINT', 'SQLBUF', 'START', 'SUCCESSFUL', 'SYNONYM', 'SYSDATE', 'TABLE', 'THEN', 'TO', 'TRIGGER', 'UID', 'UNION', 'UNIQUE', 'UPDATE', 'USER', 'VALIDATE', 'VALUES', 'VARCHAR', 'VARCHAR2', 'VIEW', 'WHENEVER', 'WHERE', 'WITH']; +const JSON_FUNCTION_REGEX = /^\s*((?:[a-z]+_){0,2}jsonb?(?:_[a-z]+){0,2})\([^)]*\)/i; +const JSON_OPERATOR_REGEX = /^\s*(->>?|@>|<@|\?[|&]?|\|{2}|#-)/i; +const TOKEN_CAPTURE_REGEX = /^\s*((?:([`"'])(?:(?!\2).|\2{2})*\2)|[\w\d\s]+|[().,;+-])/i; + +export class OracleQueryGenerator extends AbstractQueryGenerator { + constructor(options) { + super(options); + } + + /** + * Returns the value as it is stored in the Oracle DB + * + * @param {string} value + */ + getCatalogName(value) { + if (value) { + if (this.options.quoteIdentifiers === false) { + const quotedValue = this.quoteIdentifier(value); + if (quotedValue === value) { + value = value.toUpperCase(); + } + } + } + return value; + } + + /** + * Returns the tableName and schemaName as it is stored the Oracle DB + * + * @param {object|string} table + */ + getSchemaNameAndTableName(table) { + const tableName = this.getCatalogName(table.tableName || table); + const schemaName = this.getCatalogName(table.schema); + return [tableName, schemaName]; + } + + createSchema(schema) { + const quotedSchema = this.quoteIdentifier(schema); + return [ + 'DECLARE', + 'USER_FOUND BOOLEAN := FALSE;', + 'BEGIN', + ' BEGIN', + ' EXECUTE IMMEDIATE ', + this.escape(`CREATE USER ${quotedSchema} IDENTIFIED BY 12345 DEFAULT TABLESPACE USERS`), + ';', + ' EXCEPTION WHEN OTHERS THEN', + ' IF SQLCODE != -1920 THEN', + ' RAISE;', + ' ELSE', + ' USER_FOUND := TRUE;', + ' END IF;', + ' END;', + ' IF NOT USER_FOUND THEN', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT "CONNECT" TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE TABLE TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE VIEW TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE ANY TRIGGER TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE ANY PROCEDURE TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE SEQUENCE TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`GRANT CREATE SYNONYM TO ${quotedSchema}`), + ';', + ' EXECUTE IMMEDIATE ', + this.escape(`ALTER USER ${quotedSchema} QUOTA UNLIMITED ON USERS`), + ';', + ' END IF;', + 'END;' + ].join(' '); + } + + showSchemasQuery() { + return 'SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE COMMON = (\'NO\') AND USERNAME != user'; + } + + dropSchema(schema) { + return [ + 'BEGIN', + 'EXECUTE IMMEDIATE ', + this.escape(`DROP USER ${this.quoteTable(schema)} CASCADE`), + ';', + 'EXCEPTION WHEN OTHERS THEN', + ' IF SQLCODE != -1918 THEN', + ' RAISE;', + ' END IF;', + 'END;' + ].join(' '); + } + + versionQuery() { + return "SELECT VERSION_FULL FROM PRODUCT_COMPONENT_VERSION WHERE PRODUCT LIKE 'Oracle%'"; + } + + createTableQuery(tableName, attributes, options) { + const primaryKeys = [], + foreignKeys = Object.create(null), + attrStr = [], + checkStr = []; + + const values = { + table: this.quoteTable(tableName) + }; + + // Starting by dealing with all attributes + for (let attr in attributes) { + if (!Object.prototype.hasOwnProperty.call(attributes, attr)) continue; + const dataType = attributes[attr]; + attr = this.quoteIdentifier(attr); + + // ORACLE doesn't support inline REFERENCES declarations: move to the end + if (dataType.includes('PRIMARY KEY')) { + // Primary key + primaryKeys.push(attr); + if (dataType.includes('REFERENCES')) { + const match = dataType.match(/^(.+) (REFERENCES.*)$/); + attrStr.push(`${attr} ${match[1].replace(/PRIMARY KEY/, '')}`); + + // match[2] already has foreignKeys in correct format so we don't need to replace + foreignKeys[attr] = match[2]; + } else { + attrStr.push(`${attr} ${dataType.replace(/PRIMARY KEY/, '').trim()}`); + } + } else if (dataType.includes('REFERENCES')) { + // Foreign key + const match = dataType.match(/^(.+) (REFERENCES.*)$/); + attrStr.push(`${attr} ${match[1]}`); + + // match[2] already has foreignKeys in correct format so we don't need to replace + foreignKeys[attr] = match[2]; + } else { + attrStr.push(`${attr} ${dataType}`); + } + } + + values['attributes'] = attrStr.join(', '); + + const pkString = primaryKeys.map(pk => this.quoteIdentifier(pk)).join(', '); + + if (pkString.length > 0) { + values.attributes += `,PRIMARY KEY (${pkString})`; + } + + // Dealing with FKs + for (const fkey in foreignKeys) { + if (!Object.prototype.hasOwnProperty.call(foreignKeys, fkey)) continue; + // Oracle default response for FK, doesn't support if defined + if (foreignKeys[fkey].indexOf('ON DELETE NO ACTION') > -1) { + foreignKeys[fkey] = foreignKeys[fkey].replace('ON DELETE NO ACTION', ''); + } + values.attributes += `,FOREIGN KEY (${this.quoteIdentifier(fkey)}) ${foreignKeys[fkey]}`; + } + + if (checkStr.length > 0) { + values.attributes += `, ${checkStr.join(', ')}`; + } + + // Specific case for unique indexes with Oracle, we have to set the constraint on the column, if not, no FK will be possible (ORA-02270: no matching unique or primary key for this column-list) + if (options && options.indexes && options.indexes.length > 0) { + const idxToDelete = []; + options.indexes.forEach((index, idx) => { + if ('unique' in index && (index.unique === true || index.unique.length > 0 && index.unique !== false)) { + // If unique index, transform to unique constraint on column + const fields = index.fields.map(field => { + if (typeof field === 'string') { + return field; + } + return field.attribute; + + }); + + // Now we have to be sure that the constraint isn't already declared in uniqueKeys + let canContinue = true; + if (options.uniqueKeys) { + const keys = Object.keys(options.uniqueKeys); + + for (let fieldIdx = 0; fieldIdx < keys.length; fieldIdx++) { + const currUnique = options.uniqueKeys[keys[fieldIdx]]; + + if (currUnique.fields.length === fields.length) { + // lengths are the same, possible same constraint + for (let i = 0; i < currUnique.fields.length; i++) { + const field = currUnique.fields[i]; + + if (_.includes(fields, field)) { + canContinue = false; + } else { + // We have at least one different column, even if we found the same columns previously, we let the constraint be created + canContinue = true; + break; + } + } + } + } + + if (canContinue) { + const indexName = 'name' in index ? index.name : ''; + const constraintToAdd = { + name: indexName, + fields + }; + if (!('uniqueKeys' in options)) { + options.uniqueKeys = {}; + } + + options.uniqueKeys[indexName] = constraintToAdd; + idxToDelete.push(idx); + } else { + // The constraint already exists, we remove it from the list + idxToDelete.push(idx); + } + } + } + }); + idxToDelete.forEach(idx => { + options.indexes.splice(idx, 1); + }); + } + + if (options && !!options.uniqueKeys) { + _.each(options.uniqueKeys, (columns, indexName) => { + let canBeUniq = false; + + // Check if we can create the unique key + primaryKeys.forEach(primaryKey => { + // We can create an unique constraint if it's not on the primary key AND if it doesn't have unique in its definition + // We replace quotes in primary key with '' + // Primary key would be a list with double quotes in it so we remove the double quotes + primaryKey = primaryKey.replace(/"/g, ''); + + // We check if the unique indexes are already a part of primary key or not + // If it is not then we set canbeuniq to true and add a unique constraint to these fields. + // Else we can ignore unique constraint on these + if (!_.includes(columns.fields, primaryKey)) { + canBeUniq = true; + } + }); + + columns.fields.forEach(field => { + let currField = ''; + if (!_.isString(field)) { + currField = field.attribute.replace(/[.,"\s]/g, ''); + } else { + currField = field.replace(/[.,"\s]/g, ''); + } + if (currField in attributes) { + // If canBeUniq is false we need not replace the UNIQUE for the attribute + // So we replace UNIQUE with '' only if there exists a primary key + if (attributes[currField].toUpperCase().indexOf('UNIQUE') > -1 && canBeUniq) { + // We generate the attribute without UNIQUE + const attrToReplace = attributes[currField].replace('UNIQUE', ''); + // We replace in the final string + values.attributes = values.attributes.replace(attributes[currField], attrToReplace); + } + } + }); + + // Oracle cannot have an unique AND a primary key on the same fields, prior to the primary key + if (canBeUniq) { + const index = options.uniqueKeys[columns.name]; + delete options.uniqueKeys[columns.name]; + indexName = indexName.replace(/[.,\s]/g, ''); + columns.name = indexName; + options.uniqueKeys[indexName] = index; + + // Autogenerate Constraint name, if no indexName is given + if (indexName.length === 0) { + values.attributes += `,UNIQUE (${columns.fields.map(field => this.quoteIdentifier(field)).join(', ') })`; + } else { + values.attributes += + `, CONSTRAINT ${this.quoteIdentifier(indexName)} UNIQUE (${columns.fields.map(field => this.quoteIdentifier(field)).join(', ') })`; + } + } + }); + } + + // we replace single quotes by two quotes in order for the execute statement to work + const query = Utils.joinSQLFragments([ + 'CREATE TABLE', + values.table, + `(${values.attributes})` + ]); + + return Utils.joinSQLFragments([ + 'BEGIN', + 'EXECUTE IMMEDIATE', + `${this.escape(query)};`, + 'EXCEPTION WHEN OTHERS THEN', + 'IF SQLCODE != -955 THEN', + 'RAISE;', + 'END IF;', + 'END;' + ]); + } + + tableExistsQuery(table) { + const [tableName, schemaName] = this.getSchemaNameAndTableName(table); + return `SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = ${this.escape(tableName)} AND OWNER = ${table.schema ? this.escape(schemaName) : 'USER'}`; + } + + describeTableQuery(tableName, schema) { + const currTableName = this.getCatalogName(tableName.tableName || tableName); + schema = this.getCatalogName(schema); + // name, type, datalength (except number / nvarchar), datalength varchar, datalength number, nullable, default value, primary ? + return [ + 'SELECT atc.COLUMN_NAME, atc.DATA_TYPE, atc.DATA_LENGTH, atc.CHAR_LENGTH, atc.DEFAULT_LENGTH, atc.NULLABLE, ucc.constraint_type ', + 'FROM all_tab_columns atc ', + 'LEFT OUTER JOIN ', + '(SELECT acc.column_name, acc.table_name, ac.constraint_type FROM all_cons_columns acc INNER JOIN all_constraints ac ON acc.constraint_name = ac.constraint_name) ucc ', + 'ON (atc.table_name = ucc.table_name AND atc.COLUMN_NAME = ucc.COLUMN_NAME) ', + schema + ? `WHERE (atc.OWNER = ${this.escape(schema)}) ` + : 'WHERE atc.OWNER = USER ', + `AND (atc.TABLE_NAME = ${this.escape(currTableName)})`, + 'ORDER BY atc.COLUMN_NAME, CONSTRAINT_TYPE DESC' + ].join(''); + } + + renameTableQuery(before, after) { + return Utils.joinSQLFragments([ + 'ALTER TABLE', + this.quoteTable(before), + 'RENAME TO', + this.quoteTable(after) + ]); + } + + showConstraintsQuery(table) { + const tableName = this.getCatalogName(table.tableName || table); + return `SELECT CONSTRAINT_NAME constraint_name FROM user_cons_columns WHERE table_name = ${this.escape(tableName)}`; + } + + showTablesQuery() { + return 'SELECT owner as table_schema, table_name, 0 as lvl FROM all_tables where OWNER IN(SELECT USERNAME AS "schema_name" FROM ALL_USERS WHERE ORACLE_MAINTAINED = \'N\')'; + } + + dropTableQuery(tableName) { + return Utils.joinSQLFragments([ + 'BEGIN ', + 'EXECUTE IMMEDIATE \'DROP TABLE', + this.quoteTable(tableName), + 'CASCADE CONSTRAINTS PURGE\';', + 'EXCEPTION WHEN OTHERS THEN', + ' IF SQLCODE != -942 THEN', + ' RAISE;', + ' END IF;', + 'END;' + ]); + } + + /* + Modifying the indexname so that it is prefixed with the schema name + otherwise Oracle tries to add the index to the USER schema + @overide + */ + addIndexQuery(tableName, attributes, options, rawTablename) { + if (typeof tableName !== 'string' && attributes.name) { + attributes.name = `${tableName.schema}.${attributes.name}`; + } + return super.addIndexQuery(tableName, attributes, options, rawTablename); + } + + addConstraintQuery(tableName, options) { + options = options || {}; + + if (options.onUpdate) { + // Oracle does not support ON UPDATE, remove it. + delete options.onUpdate; + } + + if (options.onDelete && options.onDelete.toUpperCase() === 'NO ACTION') { + // 'ON DELETE NO ACTION' is the default option in Oracle, but it is not supported if defined + delete options.onDelete; + } + + const constraintSnippet = this.getConstraintSnippet(tableName, options); + + tableName = this.quoteTable(tableName); + return `ALTER TABLE ${tableName} ADD ${constraintSnippet};`; + } + + addColumnQuery(table, key, dataType) { + dataType.field = key; + + const attribute = Utils.joinSQLFragments([ + this.quoteIdentifier(key), + this.attributeToSQL(dataType, { + attributeName: key, + context: 'addColumn' + }) + ]); + + return Utils.joinSQLFragments([ + 'ALTER TABLE', + this.quoteTable(table), + 'ADD', + attribute + ]); + } + + removeColumnQuery(tableName, attributeName) { + return Utils.joinSQLFragments([ + 'ALTER TABLE', + this.quoteTable(tableName), + 'DROP COLUMN', + this.quoteIdentifier(attributeName), + ';' + ]); + } + + /** + * Function to add new foreign key to the attribute + * Block for add and drop foreign key constraint query + * taking the assumption that there is a single column foreign key reference always + * i.e. we always do - FOREIGN KEY (a) reference B(a) during createTable queryGenerator + * so there would be one and only one match for a constraint name for each column + * and every foreign keyed column would have a different constraint name + * Since sequelize doesn't support multiple column foreign key, added complexity to + * add the feature isn't needed + * + * @param {string} definition The operation that needs to be performed on the attribute + * @param {string|object} table The table that needs to be altered + * @param {string} attributeName The name of the attribute which would get altered + */ + _alterForeignKeyConstraint(definition, table, attributeName) { + const [tableName, schemaName] = this.getSchemaNameAndTableName(table); + const attributeNameConstant = this.escape(this.getCatalogName(attributeName)); + const schemaNameConstant = table.schema ? this.escape(this.getCatalogName(schemaName)) : 'USER'; + const tableNameConstant = this.escape(this.getCatalogName(tableName)); + const getConsNameQuery = [ + 'SELECT constraint_name INTO cons_name', + 'FROM (', + ' SELECT DISTINCT cc.owner, cc.table_name, cc.constraint_name, cc.column_name AS cons_columns', + ' FROM all_cons_columns cc, all_constraints c', + ' WHERE cc.owner = c.owner', + ' AND cc.table_name = c.table_name', + ' AND cc.constraint_name = c.constraint_name', + ' AND c.constraint_type = \'R\'', + ' GROUP BY cc.owner, cc.table_name, cc.constraint_name, cc.column_name', + ')', + 'WHERE owner =', + schemaNameConstant, + 'AND table_name =', + tableNameConstant, + 'AND cons_columns =', + attributeNameConstant, + ';' + ].join(' '); + const secondQuery = Utils.joinSQLFragments([ + `ALTER TABLE ${this.quoteIdentifier(tableName)}`, + 'ADD FOREIGN KEY', + `(${this.quoteIdentifier(attributeName)})`, + definition.replace(/.+?(?=REFERENCES)/, '') + ]); + return [ + 'BEGIN', + getConsNameQuery, + 'EXCEPTION', + 'WHEN NO_DATA_FOUND THEN', + ' CONS_NAME := NULL;', + 'END;', + 'IF CONS_NAME IS NOT NULL THEN', + ` EXECUTE IMMEDIATE 'ALTER TABLE ${this.quoteTable(table)} DROP CONSTRAINT "'||CONS_NAME||'"';`, + 'END IF;', + `EXECUTE IMMEDIATE ${this.escape(secondQuery)};` + ].join(' '); + } + + /** + * Function to alter table modify + * + * @param {string} definition The operation that needs to be performed on the attribute + * @param {object|string} table The table that needs to be altered + * @param {string} attributeName The name of the attribute which would get altered + */ + _modifyQuery(definition, table, attributeName) { + definition = definition.startsWith('BLOB') ? definition.replace('BLOB ', '') : definition; + const query = Utils.joinSQLFragments([ + 'ALTER TABLE', + this.quoteTable(table), + 'MODIFY', + this.quoteIdentifier(attributeName), + definition + ]); + const secondQuery = query.replace('NOT NULL', '').replace('NULL', ''); + return [ + 'BEGIN', + `EXECUTE IMMEDIATE ${this.escape(query)};`, + 'EXCEPTION', + 'WHEN OTHERS THEN', + ' IF SQLCODE = -1442 OR SQLCODE = -1451 THEN', + // We execute the statement without the NULL / NOT NULL clause if the first statement failed due to this + ` EXECUTE IMMEDIATE ${this.escape(secondQuery)};`, + ' ELSE', + ' RAISE;', + ' END IF;', + 'END;' + ].join(' '); + } + + changeColumnQuery(table, attributes) { + const sql = [ + 'DECLARE', + 'CONS_NAME VARCHAR2(200);', + 'BEGIN' + ]; + for (const attributeName in attributes) { + if (!Object.prototype.hasOwnProperty.call(attributes, attributeName)) continue; + const definition = attributes[attributeName]; + if (definition.match(/REFERENCES/)) { + sql.push(this._alterForeignKeyConstraint(definition, table, attributeName)); + } else { + // Building the modify query + sql.push(this._modifyQuery(definition, table, attributeName)); + } + } + sql.push('END;'); + return sql.join(' '); + } + + renameColumnQuery(tableName, attrBefore, attributes) { + const newName = Object.keys(attributes)[0]; + return `ALTER TABLE ${this.quoteTable(tableName)} RENAME COLUMN ${this.quoteIdentifier(attrBefore)} TO ${this.quoteIdentifier(newName)}`; + } + + /** + * Populates the returnAttributes array with outbind bindByPosition values + * and also the options.outBindAttributes map with bindDef for outbind of InsertQuery + * + * @param {Array} returningModelAttributes + * @param {Array} returnTypes + * @param {number} inbindLength + * @param {object} returnAttributes + * @param {object} options + * + * @private + */ + populateInsertQueryReturnIntoBinds(returningModelAttributes, returnTypes, inbindLength, returnAttributes, options) { + const oracledb = this.sequelize.connectionManager.lib; + const outBindAttributes = Object.create(null); + const outbind = []; + const outbindParam = this.bindParam(outbind, inbindLength); + returningModelAttributes.forEach((element, index) => { + // generateReturnValues function quotes identifier based on the quoteIdentifier option + // If the identifier starts with a quote we remove it else we use it as is + if (element.startsWith('"')) { + element = element.substring(1, element.length - 1); + } + outBindAttributes[element] = Object.assign(returnTypes[index]._getBindDef(oracledb), { dir: oracledb.BIND_OUT }); + const returnAttribute = `${this.format(undefined, undefined, { context: 'INSERT' }, outbindParam)}`; + returnAttributes.push(returnAttribute); + }); + options.outBindAttributes = outBindAttributes; + } + + /** + * Override of upsertQuery, Oracle specific + * Using PL/SQL for finding the row + * + * @param {object|string} tableName + * @param {Array} insertValues + * @param {Array} updateValues + * @param {Array} where + * @param {object} model + * @param {object} options + */ + upsertQuery(tableName, insertValues, updateValues, where, model, options) { + const rawAttributes = model.rawAttributes; + const updateQuery = this.updateQuery(tableName, updateValues, where, options, rawAttributes); + // This bind is passed so that the insert query starts appending to this same bind array + options.bind = updateQuery.bind; + const insertQuery = this.insertQuery(tableName, insertValues, rawAttributes, options); + + const sql = [ + 'DECLARE ', + 'BEGIN ', + updateQuery.query ? [ + updateQuery.query, + '; ', + ' IF ( SQL%ROWCOUNT = 0 ) THEN ', + insertQuery.query, + ' :isUpdate := 0; ', + 'ELSE ', + ' :isUpdate := 1; ', + ' END IF; ' + ].join('') : [ + insertQuery.query, + ' :isUpdate := 0; ', + // If there is a conflict on insert we ignore + 'EXCEPTION WHEN OTHERS THEN', + ' IF SQLCODE != -1 THEN', + ' RAISE;', + ' END IF;' + ].join(''), + 'END;' + ]; + + const query = sql.join(''); + const result = { query }; + + if (options.bindParam !== false) { + result.bind = updateQuery.bind || insertQuery.bind; + } + + return result; + } + + /** + * Returns an insert into command for multiple values. + * + * @param {string} tableName + * @param {object} fieldValueHashes + * @param {object} options + * @param {object} fieldMappedAttributes + * + * @private + */ + bulkInsertQuery(tableName, fieldValueHashes, options, fieldMappedAttributes) { + options = options || {}; + options.executeMany = true; + fieldMappedAttributes = fieldMappedAttributes || {}; + + const tuples = []; + const allColumns = {}; + const inBindBindDefMap = {}; + const outBindBindDefMap = {}; + const oracledb = this.sequelize.connectionManager.lib; + + // Generating the allColumns map + // The data is provided as an array of objects. + // Each object may contain differing numbers of attributes. + // A set of the attribute names that are used in all objects must be determined. + // The allColumns map contains the column names and indicates whether the value is generated or not + // We set allColumns[key] to true if the field is an + // auto-increment field and the value given is null and fieldMappedAttributes[key] + // is valid for the specific column else it is set to false + for (const fieldValueHash of fieldValueHashes) { + _.forOwn(fieldValueHash, (value, key) => { + allColumns[key] = fieldMappedAttributes[key] && fieldMappedAttributes[key].autoIncrement === true && value === null; + }); + } + + // Building the inbind parameter + // A list that would have inbind positions like [:1, :2, :3...] to be used in generating sql string + let inBindPosition; + // Iterating over each row of the fieldValueHashes + for (const fieldValueHash of fieldValueHashes) { + // Has each column for a row after coverting it to appropriate format using this.format function + // like ['Mick', 'Broadstone', 2022-02-16T05:24:18.949Z, 2022-02-16T05:24:18.949Z], + const tuple = []; + // A function expression for this.bindParam/options.bindparam function + // This function is passed to this.format function which inserts column values to the tuple list + // using _bindParam/_stringify function in data-type.js file + const inbindParam = options.bindParam === undefined ? this.bindParam(tuple) : options.bindParam; + // We are iterating over each col + // and pushing the given values to tuple list using this.format function + // and also simultaneously generating the bindPosition + // tempBindPostions has the inbind positions + const tempBindPositions = Object.keys(allColumns).map(key => { + if (allColumns[key] === true) { + // We had set allAttributes[key] to true since at least one row for an auto increment column was null + // If we get any other row that has this specific column as non-null we must raise an error + // Since for an auto-increment column, either all row has to be null or all row has to be a non-null + if (fieldValueHash[key] !== null) { + throw Error('For an auto-increment column either all row must be null or non-null, a mix of null and non-null is not allowed!'); + } + // Return DEFAULT for auto-increment column and if all values for the column is null in each row + return 'DEFAULT'; + } + // Sanitizes the values given by the user and pushes it to the tuple list using inBindParam function and + // also generates the inbind position for the sql string for example (:1, :2, :3.....) which is a by product of the push + return this.format(fieldValueHash[key], fieldMappedAttributes[key], { context: 'INSERT' }, inbindParam); + }); + + // Even though the bind variable positions are calculated for each row we only retain the values for the first row + // since the values will be identical + if (!inBindPosition) { + inBindPosition = tempBindPositions; + } + // Adding the row to the array of rows that will be supplied to executeMany() + tuples.push(tuple); + } + + // The columns that we are expecting to be returned from the DB like ["id1", "id2"...] + const returnColumn = []; + // The outbind positions for the returning columns like [:3, :4, :5....] + const returnColumnBindPositions = []; + // Has the columns name in which data would be inserted like ["id", "name".....] + const insertColumns = []; + // Iterating over the allColumns keys to get the bindDef for inbind and outbinds + // and also to get the list of insert and return column after applying this.quoteIdentifier + for (const key of Object.keys(allColumns)) { + // If fieldMappenAttributes[attr] is defined we generate the bindDef + // and return clause else we can skip it + if (fieldMappedAttributes[key]) { + // BindDef for the specific column + const bindDef = fieldMappedAttributes[key].type._getBindDef(oracledb); + if (allColumns[key]) { + // Binddef for outbinds + bindDef.dir = oracledb.BIND_OUT; + outBindBindDefMap[key] = bindDef; + + // Building the outbind parameter list + // ReturnColumn has the column name for example "id", "usedId", quoting depends on quoteIdentifier option + returnColumn.push(this.quoteIdentifier(key)); + // Pushing the outbind index to the returnColumnPositions to generate (:3, :4, :5) + // The start offset depend on the tuple length (bind array size of a particular row) + // the outbind position starts after the position where inbind position ends + returnColumnBindPositions.push(`:${tuples[0].length + returnColumn.length}`); + } else { + // Binddef for inbinds + bindDef.dir = oracledb.BIND_IN; + inBindBindDefMap[key] = bindDef; + } + } + // Quoting and pushing each insert column based on quoteIdentifier option + insertColumns.push(this.quoteIdentifier(key)); + } + + // Generating the sql query + let query = Utils.joinSQLFragments([ + 'INSERT', + 'INTO', + // Table name for the table in which data needs to inserted + this.quoteTable(tableName), + // Columns names for the columns of the table (example "a", "b", "c" - quoting depends on the quoteidentifier option) + `(${insertColumns.join(',')})`, + 'VALUES', + // InBind position for the insert query (for example :1, :2, :3....) + `(${inBindPosition})` + ]); + + // If returnColumn.length is > 0 + // then the returning into clause is needed + if (returnColumn.length > 0) { + options.outBindAttributes = outBindBindDefMap; + query = Utils.joinSQLFragments([ + query, + 'RETURNING', + // List of return column (for example "id", "userId"....) + `${returnColumn.join(',')}`, + 'INTO', + // List of outbindPosition (for example :4, :5, :6....) + // Start offset depends on where inbindPosition end + `${returnColumnBindPositions}` + ]); + } + + // Binding the bind variable to result + const result = { query }; + // Binding the bindParam to result + // Tuple has each row for the insert query + result.bind = tuples; + // Setting options.inbindAttribute + options.inbindAttributes = inBindBindDefMap; + return result; + } + + truncateTableQuery(tableName) { + return `TRUNCATE TABLE ${this.quoteTable(tableName)}`; + } + + deleteQuery(tableName, where, options, model) { + options = options || {}; + + const table = tableName; + + where = this.getWhereConditions(where, null, model, options); + let queryTmpl; + // delete with limit and optional condition on Oracle: DELETE FROM WHERE rowid in (SELECT rowid FROM WHERE AND rownum <= ) + // Note that the condition has to be in the subquery; otherwise, the subquery would select arbitrary rows. + if (options.limit) { + const whereTmpl = where ? ` AND ${where}` : ''; + queryTmpl = + `DELETE FROM ${this.quoteTable(table)} WHERE rowid IN (SELECT rowid FROM ${this.quoteTable(table)} WHERE rownum <= ${this.escape(options.limit)}${ + whereTmpl + })`; + } else { + const whereTmpl = where ? ` WHERE ${where}` : ''; + queryTmpl = `DELETE FROM ${this.quoteTable(table)}${whereTmpl}`; + } + return queryTmpl; + } + + showIndexesQuery(table) { + const [tableName, owner] = this.getSchemaNameAndTableName(table); + const sql = [ + 'SELECT i.index_name,i.table_name, i.column_name, u.uniqueness, i.descend, c.constraint_type ', + 'FROM all_ind_columns i ', + 'INNER JOIN all_indexes u ', + 'ON (u.table_name = i.table_name AND u.index_name = i.index_name) ', + 'LEFT OUTER JOIN all_constraints c ', + 'ON (c.table_name = i.table_name AND c.index_name = i.index_name) ', + `WHERE i.table_name = ${this.escape(tableName)}`, + ' AND u.table_owner = ', + owner ? this.escape(owner) : 'USER', + ' ORDER BY index_name, column_position' + ]; + + return sql.join(''); + } + + removeIndexQuery(tableName, indexNameOrAttributes) { + let indexName = indexNameOrAttributes; + + if (typeof indexName !== 'string') { + indexName = Utils.underscore(`${tableName }_${indexNameOrAttributes.join('_')}`); + } + + return `DROP INDEX ${this.quoteIdentifier(indexName)}`; + } + + attributeToSQL(attribute, options) { + if (!_.isPlainObject(attribute)) { + attribute = { + type: attribute + }; + } + + // TODO: Address on update cascade issue whether to throw error or ignore. + // Add this to documentation when merging to sequelize-main + // ON UPDATE CASCADE IS NOT SUPPORTED BY ORACLE. + attribute.onUpdate = ''; + + // handle self referential constraints + if (attribute.references) { + if (attribute.Model && attribute.Model.tableName === attribute.references.model) { + this.sequelize.log( + 'Oracle does not support self referencial constraints, ' + + 'we will remove it but we recommend restructuring your query' + ); + attribute.onDelete = ''; + } + } + + let template; + + template = attribute.type.toSql ? attribute.type.toSql() : ''; + if (attribute.type instanceof DataTypes.JSON) { + template += ` CHECK (${this.quoteIdentifier(options.attributeName)} IS JSON)`; + return template; + } + if (Utils.defaultValueSchemable(attribute.defaultValue)) { + template += ` DEFAULT ${this.escape(attribute.defaultValue)}`; + } + if (attribute.allowNull === false) { + template += ' NOT NULL'; + } + if (attribute.type instanceof DataTypes.ENUM) { + if (attribute.type.values && !attribute.values) attribute.values = attribute.type.values; + // enums are a special case + template += + ` CHECK (${this.quoteIdentifier(options.attributeName)} IN(${ + _.map(attribute.values, value => { + return this.escape(value); + }).join(', ') + }))`; + return template; + } + if (attribute.type instanceof DataTypes.BOOLEAN) { + template += + ` CHECK (${this.quoteIdentifier(options.attributeName)} IN('1', '0'))`; + return template; + } + if (attribute.autoIncrement) { + template = ' NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY'; + } else if (attribute.type && attribute.type.key === DataTypes.DOUBLE.key) { + template = attribute.type.toSql(); + } else if (attribute.type) { + // setting it to false because oracle doesn't support unsigned int so put a check to make it behave like unsigned int + let unsignedTemplate = ''; + if (attribute.type._unsigned) { + attribute.type._unsigned = false; + unsignedTemplate += ` check(${this.quoteIdentifier(options.attributeName)} >= 0)`; + } + template = attribute.type.toString(); + + // Blobs/texts cannot have a defaultValue + if ( + attribute.type && + attribute.type !== 'TEXT' && + attribute.type._binary !== true && + Utils.defaultValueSchemable(attribute.defaultValue) + ) { + template += ` DEFAULT ${this.escape(attribute.defaultValue)}`; + } + + if (!attribute.autoIncrement) { + // If autoincrement, not null is set automatically + if (attribute.allowNull === false) { + template += ' NOT NULL'; + } else if (!attribute.primaryKey && !Utils.defaultValueSchemable(attribute.defaultValue)) { + template += ' NULL'; + } + } + template += unsignedTemplate; + } else { + template = ''; + } + + if (attribute.unique === true && !attribute.primaryKey) { + template += ' UNIQUE'; + } + + if (attribute.primaryKey) { + template += ' PRIMARY KEY'; + } + + if ((!options || !options.withoutForeignKeyConstraints) && attribute.references) { + template += ` REFERENCES ${this.quoteTable(attribute.references.model)}`; + + if (attribute.references.key) { + template += ` (${this.quoteIdentifier(attribute.references.key) })`; + } else { + template += ` (${this.quoteIdentifier('id') })`; + } + + if (attribute.onDelete && attribute.onDelete.toUpperCase() !== 'NO ACTION') { + template += ` ON DELETE ${attribute.onDelete.toUpperCase()}`; + } + } + + return template; + } + attributesToSQL(attributes, options) { + const result = {}; + + for (const key in attributes) { + const attribute = attributes[key]; + const attributeName = attribute.field || key; + result[attributeName] = this.attributeToSQL(attribute, { attributeName, ...options }); + } + + return result; + } + + createTrigger() { + throwMethodUndefined('createTrigger'); + } + + dropTrigger() { + throwMethodUndefined('dropTrigger'); + } + + renameTrigger() { + throwMethodUndefined('renameTrigger'); + } + + createFunction() { + throwMethodUndefined('createFunction'); + } + + dropFunction() { + throwMethodUndefined('dropFunction'); + } + + renameFunction() { + throwMethodUndefined('renameFunction'); + } + + getConstraintsOnColumn(table, column) { + const [tableName, schemaName] = this.getSchemaNameAndTableName(table); + column = this.getCatalogName(column); + const sql = [ + 'SELECT CONSTRAINT_NAME FROM user_cons_columns WHERE TABLE_NAME = ', + this.escape(tableName), + ' and OWNER = ', + table.schema ? this.escape(schemaName) : 'USER', + ' and COLUMN_NAME = ', + this.escape(column), + ' AND POSITION IS NOT NULL ORDER BY POSITION' + ].join(''); + + return sql; + } + + getForeignKeysQuery(table) { + // We don't call quoteTable as we don't want the schema in the table name, Oracle seperates it on another field + const [tableName, schemaName] = this.getSchemaNameAndTableName(table); + const sql = [ + 'SELECT DISTINCT a.table_name "tableName", a.constraint_name "constraintName", a.owner "owner", a.column_name "columnName",', + ' b.table_name "referencedTableName", b.column_name "referencedColumnName"', + ' FROM all_cons_columns a', + ' JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name', + ' JOIN all_cons_columns b ON c.owner = b.owner AND c.r_constraint_name = b.constraint_name', + " WHERE c.constraint_type = 'R'", + ' AND a.table_name = ', + this.escape(tableName), + ' AND a.owner = ', + table.schema ? this.escape(schemaName) : 'USER', + ' ORDER BY a.table_name, a.constraint_name' + ].join(''); + + return sql; + } + + dropForeignKeyQuery(tableName, foreignKey) { + return this.dropConstraintQuery(tableName, foreignKey); + } + + getPrimaryKeyConstraintQuery(table) { + const [tableName, schemaName] = this.getSchemaNameAndTableName(table); + const sql = [ + 'SELECT cols.column_name, atc.identity_column ', + 'FROM all_constraints cons, all_cons_columns cols ', + 'INNER JOIN all_tab_columns atc ON(atc.table_name = cols.table_name AND atc.COLUMN_NAME = cols.COLUMN_NAME )', + 'WHERE cols.table_name = ', + this.escape(tableName), + 'AND cols.owner = ', + table.schema ? this.escape(schemaName) : 'USER ', + "AND cons.constraint_type = 'P' ", + 'AND cons.constraint_name = cols.constraint_name ', + 'AND cons.owner = cols.owner ', + 'ORDER BY cols.table_name, cols.position' + ].join(''); + + return sql; + } + + dropConstraintQuery(tableName, constraintName) { + return `ALTER TABLE ${this.quoteTable(tableName)} DROP CONSTRAINT ${constraintName}`; + } + + setIsolationLevelQuery(value, options) { + if (options.parent) { + return; + } + + switch (value) { + case Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED: + case Transaction.ISOLATION_LEVELS.READ_COMMITTED: + return 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED;'; + case Transaction.ISOLATION_LEVELS.REPEATABLE_READ: + // Serializable mode is equal to Snapshot Isolation (SI) + // defined in ANSI std. + return 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;'; + default: + throw new Error(`isolation level "${value}" is not supported`); + } + } + + getAliasToken() { + return ''; + } + + startTransactionQuery(transaction) { + if (transaction.parent) { + return `SAVEPOINT ${this.quoteIdentifier(transaction.name)}`; + } + + return 'BEGIN TRANSACTION'; + } + + commitTransactionQuery(transaction) { + if (transaction.parent) { + return; + } + + return 'COMMIT TRANSACTION'; + } + + rollbackTransactionQuery(transaction) { + if (transaction.parent) { + return `ROLLBACK TO SAVEPOINT ${this.quoteIdentifier(transaction.name)}`; + } + + return 'ROLLBACK TRANSACTION'; + } + + handleSequelizeMethod(smth, tableName, factory, options, prepend) { + let str; + if (smth instanceof Utils.Json) { + // Parse nested object + if (smth.conditions) { + const conditions = this.parseConditionObject(smth.conditions).map(condition => + `${this.jsonPathExtractionQuery(condition.path[0], _.tail(condition.path))} = '${condition.value}'` + ); + + return conditions.join(' AND '); + } + if (smth.path) { + + // Allow specifying conditions using the sqlite json functions + if (this._checkValidJsonStatement(smth.path)) { + str = smth.path; + } else { + // Also support json property accessors + const paths = _.toPath(smth.path); + const column = paths.shift(); + str = this.jsonPathExtractionQuery(column, paths); + } + if (smth.value) { + str += util.format(' = %s', this.escape(smth.value)); + } + + return str; + } + } + if (smth instanceof Utils.Cast) { + if (smth.val instanceof Utils.SequelizeMethod) { + str = this.handleSequelizeMethod(smth.val, tableName, factory, options, prepend); + if (smth.type === 'boolean') { + str = `(CASE WHEN ${str}='true' THEN 1 ELSE 0 END)`; + return `CAST(${str} AS NUMBER)`; + } if (smth.type === 'timestamptz' && /json_value\(/.test(str)) { + str = str.slice(0, -1); + return `${str} RETURNING TIMESTAMP WITH TIME ZONE)`; + } + } + } + return super.handleSequelizeMethod(smth, tableName, factory, options, prepend); + } + + _checkValidJsonStatement(stmt) { + if (typeof stmt !== 'string') { + return false; + } + + let currentIndex = 0; + let openingBrackets = 0; + let closingBrackets = 0; + let hasJsonFunction = false; + let hasInvalidToken = false; + + while (currentIndex < stmt.length) { + const string = stmt.substr(currentIndex); + const functionMatches = JSON_FUNCTION_REGEX.exec(string); + if (functionMatches) { + currentIndex += functionMatches[0].indexOf('('); + hasJsonFunction = true; + continue; + } + + const operatorMatches = JSON_OPERATOR_REGEX.exec(string); + if (operatorMatches) { + currentIndex += operatorMatches[0].length; + hasJsonFunction = true; + continue; + } + + const tokenMatches = TOKEN_CAPTURE_REGEX.exec(string); + if (tokenMatches) { + const capturedToken = tokenMatches[1]; + if (capturedToken === '(') { + openingBrackets++; + } else if (capturedToken === ')') { + closingBrackets++; + } else if (capturedToken === ';') { + hasInvalidToken = true; + break; + } + currentIndex += tokenMatches[0].length; + continue; + } + + break; + } + + // Check invalid json statement + if (hasJsonFunction && (hasInvalidToken || openingBrackets !== closingBrackets)) { + throw new Error(`Invalid json statement: ${stmt}`); + } + + // return true if the statement has valid json function + return hasJsonFunction; + } + + jsonPathExtractionQuery(column, path) { + let paths = _.toPath(path); + const quotedColumn = this.isIdentifierQuoted(column) ? column : this.quoteIdentifier(column); + + paths = paths.map(subPath => { + return /\D/.test(subPath) ? Utils.addTicks(subPath, '"') : subPath; + }); + + const pathStr = this.escape(['$'].concat(paths).join('.').replace(/\.(\d+)(?:(?=\.)|$)/g, (__, digit) => `[${digit}]`)); + + return `json_value(${quotedColumn},${pathStr})`; + } + + addLimitAndOffset(options, model) { + let fragment = ''; + const offset = options.offset || 0, + isSubQuery = options.hasIncludeWhere || options.hasIncludeRequired || options.hasMultiAssociation; + + let orders = {}; + if (options.order) { + orders = this.getQueryOrders(options, model, isSubQuery); + } + + if (options.limit || options.offset) { + // Add needed order by clause only when it is not provided + if (!orders.mainQueryOrder || !orders.mainQueryOrder.length || isSubQuery && (!orders.subQueryOrder || !orders.subQueryOrder.length)) { + const tablePkFragment = `${this.quoteTable(options.tableAs || model.name)}.${this.quoteIdentifier(model.primaryKeyField)}`; + fragment += ` ORDER BY ${tablePkFragment}`; + } + + if (options.offset || options.limit) { + fragment += ` OFFSET ${this.escape(offset)} ROWS`; + } + + if (options.limit) { + fragment += ` FETCH NEXT ${this.escape(options.limit)} ROWS ONLY`; + } + } + + return fragment; + } + + booleanValue(value) { + return value ? 1 : 0; + } + + quoteIdentifier(identifier, force = false) { + const optForceQuote = force; + const optQuoteIdentifiers = this.options.quoteIdentifiers !== false; + const rawIdentifier = Utils.removeTicks(identifier, '"'); + const regExp = /^(([\w][\w\d_]*))$/g; + + if ( + optForceQuote !== true && + optQuoteIdentifiers === false && + regExp.test(rawIdentifier) && + !ORACLE_RESERVED_WORDS.includes(rawIdentifier.toUpperCase()) + ) { + // In Oracle, if tables, attributes or alias are created double-quoted, + // they are always case sensitive. If they contain any lowercase + // characters, they must always be double-quoted otherwise it + // would get uppercased by the DB. + // Here, we strip quotes if we don't want case sensitivity. + return rawIdentifier; + } + return Utils.addTicks(rawIdentifier, '"'); + } + + /** + * It causes bindbyPosition like :1, :2, :3 + * We pass the val parameter so that the outBind indexes + * starts after the inBind indexes end + * + * @param {Array} bind + * @param {number} posOffset + */ + bindParam(bind, posOffset = 0) { + return value => { + bind.push(value); + return `:${bind.length + posOffset}`; + }; + } + + /** + * Returns the authenticate test query string + */ + authTestQuery() { + return 'SELECT 1+1 AS result FROM DUAL'; + } +} + +/* istanbul ignore next */ +function throwMethodUndefined(methodName) { + throw new Error(`The method "${methodName}" is not defined! Please add it to your sql dialect.`); +} diff --git a/src/dialects/oracle/query-interface.js b/src/dialects/oracle/query-interface.js new file mode 100644 index 000000000000..ac188bbaae11 --- /dev/null +++ b/src/dialects/oracle/query-interface.js @@ -0,0 +1,85 @@ +// Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +'use strict'; +const { QueryInterface } = require('../abstract/query-interface'); +const QueryTypes = require('../../query-types'); + +const _ = require('lodash'); +/** + * The interface that Sequelize uses to talk with Oracle database + */ +export class OracleQueryInterface extends QueryInterface { + + /** + * Upsert + * + * @param {string} tableName table to upsert on + * @param {object} insertValues values to be inserted, mapped to field name + * @param {object} updateValues values to be updated, mapped to field name + * @param {object} where where conditions, which can be used for UPDATE part when INSERT fails + * @param {object} options query options + * + * @returns {Promise} Resolves an array with + */ + async upsert(tableName, insertValues, updateValues, where, options) { + options = { ...options }; + + const model = options.model; + const primaryKeys = Object.values(model.primaryKeys).map(item => item.field); + const uniqueKeys = Object.values(model.uniqueKeys).filter(c => c.fields.length > 0).map(c => c.fields); + const indexKeys = Object.values(model._indexes).filter(c => c.unique && c.fields.length > 0).map(c => c.fields); + + options.type = QueryTypes.UPSERT; + options.updateOnDuplicate = Object.keys(updateValues); + options.upsertKeys = []; + + // For fields in updateValues, try to find a constraint or unique index + // that includes given field. Only first matching upsert key is used. + for (const field of options.updateOnDuplicate) { + const uniqueKey = uniqueKeys.find(fields => fields.includes(field)); + if (uniqueKey) { + options.upsertKeys = uniqueKey; + break; + } + + const indexKey = indexKeys.find(fields => fields.includes(field)); + if (indexKey) { + options.upsertKeys = indexKey; + break; + } + } + + // Always use PK, if no constraint available OR update data contains PK + if ( + options.upsertKeys.length === 0 + || _.intersection(options.updateOnDuplicate, primaryKeys).length + ) { + options.upsertKeys = primaryKeys; + } + + options.upsertKeys = _.uniq(options.upsertKeys); + + let whereHasNull = false; + + primaryKeys.forEach(element => { + if (where[element] === null) { + whereHasNull = true; + } + }); + + if (whereHasNull === true) { + where = options.upsertKeys.reduce((result, attribute) => { + result[attribute] = insertValues[attribute]; + return result; + }, {}); + } + + const sql = this.queryGenerator.upsertQuery(tableName, insertValues, updateValues, where, model, options); + // we need set this to undefined otherwise sequelize would raise an error + // Error: Both `sql.bind` and `options.bind` cannot be set at the same time + if (sql.bind) { + options.bind = undefined; + } + return await this.sequelize.query(sql, options); + } +} diff --git a/src/dialects/oracle/query.js b/src/dialects/oracle/query.js new file mode 100644 index 000000000000..494b9a50822e --- /dev/null +++ b/src/dialects/oracle/query.js @@ -0,0 +1,675 @@ +// Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved + +'use strict'; + +const AbstractQuery = require('../abstract/query'); +const SequelizeErrors = require('../../errors'); +const parserStore = require('../parserStore')('oracle'); +const _ = require('lodash'); +const Utils = require('../../utils'); +const { logger } = require('../../utils/logger'); + +const debug = logger.debugContext('sql:oracle'); + +export class OracleQuery extends AbstractQuery { + constructor(connection, sequelize, options) { + super(connection, sequelize, options); + this.options = _.extend( + { + logging: console.log, + plain: false, + raw: false + }, + options || {} + ); + + this.checkLoggingOption(); + this.outFormat = options.outFormat || this.sequelize.connectionManager.lib.OBJECT; + } + + getInsertIdField() { + return 'id'; + } + + getExecOptions() { + const execOpts = { outFormat: this.outFormat, autoCommit: this.autoCommit }; + + // We set the oracledb + const oracledb = this.sequelize.connectionManager.lib; + + if (this.model && this.isSelectQuery()) { + const fInfo = {}; + const keys = Object.keys(this.model.tableAttributes); + for (const key of keys) { + const keyValue = this.model.tableAttributes[key]; + if (keyValue.type.key === 'DECIMAL') { + fInfo[key] = { type: oracledb.STRING }; + } + // Fetching BIGINT as string since, node-oracledb doesn't support JS BIGINT yet + if (keyValue.type.key === 'BIGINT') { + fInfo[key] = { type: oracledb.STRING }; + } + } + if ( fInfo ) { + execOpts.fetchInfo = fInfo; + } + } + return execOpts; + } + + /** + * convert binding values for unsupported + * types in connector library + * + * @param {string} bindingDictionary a string representing the key to scan + * @param {object} oracledb native oracle library + * @private + */ + _convertBindAttributes(bindingDictionary, oracledb) { + if (this.model && this.options[bindingDictionary]) { + // check against model if we have some BIGINT + const keys = Object.keys(this.model.tableAttributes); + for (const key of keys) { + const keyValue = this.model.tableAttributes[key]; + if (keyValue.type.key === 'BIGINT') { + const oldBinding = this.options[bindingDictionary][key]; + if (oldBinding) { + this.options[bindingDictionary][key] = { + ...oldBinding, + type: oracledb.STRING, + maxSize: 10000000 //TOTALLY ARBITRARY Number to prevent query failure + }; + } + } + } + } + } + + async run(sql, parameters) { + // We set the oracledb + const oracledb = this.sequelize.connectionManager.lib; + const complete = this._logQuery(sql, debug, parameters); + const outParameters = []; + const bindParameters = []; + const bindDef = []; + + if (!sql.match(/END;$/)) { + this.sql = sql.replace(/; *$/, ''); + } else { + this.sql = sql; + } + + // When this.options.bindAttributes exists then it is an insertQuery/upsertQuery + // So we insert the return bind direction and type + if (this.options.outBindAttributes && (Array.isArray(parameters) || _.isPlainObject(parameters))) { + this._convertBindAttributes('outBindAttributes', oracledb); + outParameters.push(...Object.values(this.options.outBindAttributes)); + // For upsertQuery we need to push the bindDef for isUpdate + if (this.isUpsertQuery()) { + outParameters.push({ dir: oracledb.BIND_OUT }); + } + } + + this.bindParameters = outParameters; + // construct input binds from parameters for single row insert execute call + // ex: [3, 4,...] + if (Array.isArray(parameters) || _.isPlainObject(parameters)) { + if (this.options.executeMany) { + // Constructing BindDefs for ExecuteMany call + // Building the bindDef for in and out binds + this._convertBindAttributes('inbindAttributes', oracledb); + bindDef.push(...Object.values(this.options.inbindAttributes)); + bindDef.push(...outParameters); + this.bindParameters = parameters; + } else if (this.isRawQuery()) { + this.bindParameters = parameters; + } else { + Object.values(parameters).forEach(value => { + bindParameters.push(value); + }); + bindParameters.push(...outParameters); + Object.assign(this.bindParameters, bindParameters); + } + } + + // TRANSACTION SUPPORT + if (this.sql.startsWith('BEGIN TRANSACTION')) { + this.autocommit = false; + return Promise.resolve(); + } + if (this.sql.startsWith('SET AUTOCOMMIT ON')) { + this.autocommit = true; + return Promise.resolve(); + } + if (this.sql.startsWith('SET AUTOCOMMIT OFF')) { + this.autocommit = false; + return Promise.resolve(); + } + if (this.sql.startsWith('DECLARE x NUMBER')) { + // Calling a stored procedure for bulkInsert with NO attributes, returns nothing + if (this.autoCommit === undefined) { + if (this.connection.uuid) { + this.autoCommit = false; + } else { + this.autoCommit = true; + } + } + + try { + await this.connection.execute(this.sql, this.bindParameters, { autoCommit: this.autoCommit }); + return Object.create(null); + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + if (this.sql.startsWith('BEGIN')) { + // Call to stored procedures - BEGIN TRANSACTION has been treated before + if (this.autoCommit === undefined) { + if (this.connection.uuid) { + this.autoCommit = false; + } else { + this.autoCommit = true; + } + } + + try { + const result = await this.connection.execute(this.sql, this.bindParameters, { + outFormat: this.outFormat, + autoCommit: this.autoCommit + }); + if (!Array.isArray(result.outBinds)) { + return [result.outBinds]; + } + return result.outBinds; + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + if (this.sql.startsWith('COMMIT TRANSACTION')) { + try { + await this.connection.commit(); + return Object.create(null); + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + if (this.sql.startsWith('ROLLBACK TRANSACTION')) { + try { + await this.connection.rollback(); + return Object.create(null); + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + if (this.sql.startsWith('SET TRANSACTION')) { + try { + await this.connection.execute(this.sql, [], { autoCommit: false }); + return Object.create(null); + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + // QUERY SUPPORT + // As Oracle does everything in transaction, if autoCommit is not defined, we set it to true + if (this.autoCommit === undefined) { + if (this.connection.uuid) { + this.autoCommit = false; + } else { + this.autoCommit = true; + } + } + + // inbind parameters added byname. merge them + if ('inputParameters' in this.options && this.options.inputParameters !== null) { + Object.assign(this.bindParameters, this.options.inputParameters); + } + const execOpts = this.getExecOptions(); + if (this.options.executeMany && bindDef.length > 0) { + execOpts.bindDefs = bindDef; + } + const executePromise = this.options.executeMany ? this.connection.executeMany(this.sql, this.bindParameters, execOpts) : this.connection.execute(this.sql, this.bindParameters, execOpts); + try { + const result = await executePromise; + return this.formatResults(result); + } catch (error) { + throw this.formatError(error); + } finally { + complete(); + } + } + + /** + * The parameters to query.run function are built here + * + * @param {string} sql + * @param {Array} values + * @param {string} dialect + */ + static formatBindParameters(sql, values, dialect) { + + const replacementFunc = (match, key, values) => { + if (values[key] !== undefined) { + return `:${key}`; + } + return undefined; + }; + sql = AbstractQuery.formatBindParameters(sql, values, dialect, replacementFunc)[0]; + + return [sql, values]; + } + + /** + * Building the attribute map by matching the column names received + * from DB and the one in rawAttributes + * to sequelize format + * + * @param {object} attrsMap + * @param {object} rawAttributes + * @private + */ + _getAttributeMap(attrsMap, rawAttributes) { + attrsMap = Object.assign(attrsMap, _.reduce(rawAttributes, (mp, _, key) => { + const catalogKey = this.sequelize.queryInterface.queryGenerator.getCatalogName(key); + mp[catalogKey] = key; + return mp; + }, {})); + } + + /** + * Process rows received from the DB. + * Use parse function to parse the returned value + * to sequelize format + * + * @param {Array} rows + * @private + */ + _processRows(rows) { + let result = rows; + let attrsMap = {}; + + // When quoteIdentifiers is false we need to map the DB column names + // To the one in attribute list + if (this.sequelize.options.quoteIdentifiers === false) { + // Building the attribute map from this.options.attributes + // Needed in case of an aggregate function + attrsMap = _.reduce(this.options.attributes, (mp, v) => { + // Aggregate function is of form + // Fn {fn: 'min', min}, so we have the name in index one of the object + if (typeof v === 'object') { + v = v[1]; + } + const catalogv = this.sequelize.queryInterface.queryGenerator.getCatalogName(v); + mp[catalogv] = v; + return mp; + }, {}); + + + // Building the attribute map by matching the column names received + // from DB and the one in model.rawAttributes + if (this.model) { + this._getAttributeMap(attrsMap, this.model.rawAttributes); + } + + // If aliasesmapping exists we update the attribute map + if (this.options.aliasesMapping) { + const obj = Object.fromEntries(this.options.aliasesMapping); + rows = rows + .map(row => _.toPairs(row) + .reduce((acc, [key, value]) => { + const mapping = Object.values(obj).find(element => { + const catalogElement = this.sequelize.queryInterface.queryGenerator.getCatalogName(element); + return catalogElement === key; + }); + if (mapping) + acc[mapping || key] = value; + return acc; + }, {}) + ); + } + + // Modify the keys into the format that sequelize expects + result = rows.map(row => { + return _.mapKeys(row, (value, key) => { + const targetAttr = attrsMap[key]; + if (typeof targetAttr === 'string' && targetAttr !== key) { + return targetAttr; + } + return key; + }); + }); + } + + // We parse the value received from the DB based on its datatype + if (this.model) { + result = result.map(row => { + return _.mapValues(row, (value, key) => { + if (this.model.rawAttributes[key] && this.model.rawAttributes[key].type) { + let typeid = this.model.rawAttributes[key].type.toLocaleString(); + if (this.model.rawAttributes[key].type.key === 'JSON') { + value = JSON.parse(value); + } + // For some types, the "name" of the type is returned with the length, we remove it + // For Boolean we skip this because BOOLEAN is mapped to CHAR(1) and we dont' want to + // remove the (1) for BOOLEAN + if (typeid.indexOf('(') > -1 && this.model.rawAttributes[key].type.key !== 'BOOLEAN') { + typeid = typeid.substr(0, typeid.indexOf('(')); + } + const parse = parserStore.get(typeid); + if (value !== null & !!parse) { + value = parse(value); + } + } + return value; + }); + }); + } + + return result; + } + + /** + * High level function that handles the results of a query execution. + * Example: + * Oracle format : + * { rows: //All rows + [ [ 'Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production' ], + [ 'PL/SQL Release 11.2.0.1.0 - Production' ], + [ 'CORE\t11.2.0.1.0\tProduction' ], + [ 'TNS for 64-bit Windows: Version 11.2.0.1.0 - Production' ], + [ 'NLSRTL Version 11.2.0.1.0 - Production' ] ], + resultSet: undefined, + outBinds: undefined, //Used for dbms_put.line + rowsAffected: undefined, //Number of rows affected + metaData: [ { name: 'BANNER' } ] } + * + * @param {Array} data - The result of the query execution. + */ + formatResults(data) { + let result = this.instance; + if (this.isInsertQuery(data)) { + let insertData; + if (data.outBinds) { + const keys = Object.keys(this.options.outBindAttributes); + insertData = data.outBinds; + // For one row insert out bind array is 1D array + // we convert it to 2D array for uniformity + if (this.instance) { + insertData = [insertData]; + } + // Mapping the bind parameter to their values + const res = insertData.map(row =>{ + const obj = {}; + row.forEach((element, index) =>{ + obj[keys[index]] = element[0]; + }); + return obj; + }); + insertData = res; + // For bulk insert this.insert is undefined + // we map result to res, for one row insert + // result needs to be this.instance + if (!this.instance) { + result = res; + } + } + this.handleInsertQuery(insertData); + return [result, data.rowsAffected]; + } + if (this.isShowTablesQuery()) { + result = this.handleShowTablesQuery(data.rows); + } else if (this.isDescribeQuery()) { + result = {}; + // Getting the table name on which we are doing describe query + const table = Object.keys(this.sequelize.models); + const modelAttributes = {}; + // Get the model raw attributes + if (this.sequelize.models && table.length > 0) { + this._getAttributeMap(modelAttributes, this.sequelize.models[table[0]].rawAttributes); + } + data.rows.forEach(_result => { + if (_result.Default) { + _result.Default = _result.Default.replace("('", '') + .replace("')", '') + .replace(/'/g, ''); /* jshint ignore: line */ + } + + if (!(modelAttributes[_result.COLUMN_NAME] in result)) { + let key = modelAttributes[_result.COLUMN_NAME]; + if (!key) { + key = _result.COLUMN_NAME; + } + + result[key] = { + type: _result.DATA_TYPE.toUpperCase(), + allowNull: _result.NULLABLE === 'N' ? false : true, + defaultValue: undefined, + primaryKey: _result.CONSTRAINT_TYPE === 'P' + }; + } + }); + } else if (this.isShowIndexesQuery()) { + result = this.handleShowIndexesQuery(data.rows); + } else if (this.isSelectQuery()) { + const rows = data.rows; + const result = this._processRows(rows); + return this.handleSelectQuery(result); + } else if (this.isCallQuery()) { + result = data.rows[0]; + } else if (this.isUpdateQuery()) { + result = [result, data.rowsAffected]; + } else if (this.isBulkUpdateQuery()) { + result = data.rowsAffected; + } else if (this.isBulkDeleteQuery()) { + result = data.rowsAffected; + } else if (this.isVersionQuery()) { + const version = data.rows[0].VERSION_FULL; + if (version) { + const versions = version.split('.'); + result = `${versions[0]}.${versions[1]}.${versions[2]}`; + } else { + result = '0.0.0'; + } + } else if (this.isForeignKeysQuery()) { + result = data.rows; + } else if (this.isUpsertQuery()) { + // Upsert Query, will return nothing + data = data.outBinds; + const keys = Object.keys(this.options.outBindAttributes); + const obj = {}; + for (const k in keys) { + obj[keys[k]] = data[k]; + } + obj.isUpdate = data[data.length - 1]; + data = obj; + result = [{ isNewRecord: data.isUpdate, value: data }, data.isUpdate == 0]; + } else if (this.isShowConstraintsQuery()) { + result = this.handleShowConstraintsQuery(data); + } else if (this.isRawQuery()) { + // If data.rows exists then it is a select query + // Hence we would have two components + // metaData and rows and we return them + // as [data.rows, data.metaData] + // Else it is result of update/upsert/insert query + // and it has no rows so we return [data, data] + if (data && data.rows) { + return [data.rows, data.metaData]; + } + return [data, data]; + } + + return result; + } + + handleShowConstraintsQuery(data) { + // Convert snake_case keys to camelCase as its generated by stored procedure + return data.rows.map(result => { + const constraint = {}; + for (const key in result) { + constraint[_.camelCase(key)] = result[key].toLowerCase(); + } + return constraint; + }); + } + + handleShowTablesQuery(results) { + return results.map(resultSet => { + return { + tableName: resultSet.TABLE_NAME, + schema: resultSet.TABLE_SCHEMA + }; + }); + } + + formatError(err) { + let match; + // ORA-00001: unique constraint (USER.XXXXXXX) violated + match = err.message.match(/unique constraint ([\s\S]*) violated/); + if (match && match.length > 1) { + match[1] = match[1].replace('(', '').replace(')', '').split('.')[1]; // As we get (SEQUELIZE.UNIQNAME), we replace to have UNIQNAME + const errors = []; + let fields = [], + message = 'Validation error', + uniqueKey = null; + + if (this.model) { + const uniqueKeys = Object.keys(this.model.uniqueKeys); + + const currKey = uniqueKeys.find(key => { + // We check directly AND with quotes -> "a"" === a || "a" === "a" + return key.toUpperCase() === match[1].toUpperCase() || key.toUpperCase() === `"${match[1].toUpperCase()}"`; + }); + + if (currKey) { + uniqueKey = this.model.uniqueKeys[currKey]; + fields = uniqueKey.fields; + } + + if (uniqueKey && !!uniqueKey.msg) { + message = uniqueKey.msg; + } + + fields.forEach(field => { + errors.push( + new SequelizeErrors.ValidationErrorItem( + this.getUniqueConstraintErrorMessage(field), + 'unique violation', + field, + null + ) + ); + }); + } + + return new SequelizeErrors.UniqueConstraintError({ + message, + errors, + err, + fields + }); + } + + // ORA-02291: integrity constraint (string.string) violated - parent key not found / ORA-02292: integrity constraint (string.string) violated - child record found + match = err.message.match(/ORA-02291/) || err.message.match(/ORA-02292/); + if (match && match.length > 0) { + return new SequelizeErrors.ForeignKeyConstraintError({ + fields: null, + index: match[1], + parent: err + }); + } + + // ORA-02443: Cannot drop constraint - nonexistent constraint + match = err.message.match(/ORA-02443/); + if (match && match.length > 0) { + return new SequelizeErrors.UnknownConstraintError(match[1]); + } + + return new SequelizeErrors.DatabaseError(err); + } + + isShowIndexesQuery() { + return this.sql.indexOf('SELECT i.index_name,i.table_name, i.column_name, u.uniqueness') > -1; + } + + isSelectCountQuery() { + return this.sql.toUpperCase().indexOf('SELECT COUNT(') > -1; + } + + handleShowIndexesQuery(data) { + const acc = []; + + // We first treat the datas + data.forEach(indexRecord => { + // We create the object + if (!acc[indexRecord.INDEX_NAME]) { + acc[indexRecord.INDEX_NAME] = { + unique: indexRecord.UNIQUENESS === 'UNIQUE' ? true : false, + primary: indexRecord.CONSTRAINT_TYPE === 'P', + name: indexRecord.INDEX_NAME.toLowerCase(), + tableName: indexRecord.TABLE_NAME.toLowerCase(), + type: undefined + }; + acc[indexRecord.INDEX_NAME].fields = []; + } + + // We create the fields + acc[indexRecord.INDEX_NAME].fields.push({ + attribute: indexRecord.COLUMN_NAME, + length: undefined, + order: indexRecord.DESCEND, + collate: undefined + }); + }); + + const returnIndexes = []; + const accKeys = Object.keys(acc); + for (const accKey of accKeys) { + const columns = {}; + columns.fields = acc[accKey].fields; + // We are generating index field name in the format sequelize expects + // to avoid creating a unique index on auto-generated index name + if (acc[accKey].name.match(/sys_c[0-9]*/)) { + acc[accKey].name = Utils.nameIndex(columns, acc[accKey].tableName).name; + } + returnIndexes.push(acc[accKey]); + } + return returnIndexes; + } + + handleInsertQuery(results, metaData) { + if (this.instance && results.length > 0) { + if ('pkReturnVal' in results[0]) { + // The PK of the table is a reserved word (ex : uuid), we have to change the name in the result for the model to find the value correctly + results[0][this.model.primaryKeyAttribute] = results[0].pkReturnVal; + delete results[0].pkReturnVal; + } + // add the inserted row id to the instance + const autoIncrementField = this.model.autoIncrementAttribute; + let autoIncrementFieldAlias = null, + id = null; + + if ( + Object.prototype.hasOwnProperty.call(this.model.rawAttributes, autoIncrementField) && + this.model.rawAttributes[autoIncrementField].field !== undefined + ) + autoIncrementFieldAlias = this.model.rawAttributes[autoIncrementField].field; + + id = id || results && results[0][this.getInsertIdField()]; + id = id || metaData && metaData[this.getInsertIdField()]; + id = id || results && results[0][autoIncrementField]; + id = id || autoIncrementFieldAlias && results && results[0][autoIncrementFieldAlias]; + + this.instance[autoIncrementField] = id; + } + } +} diff --git a/src/dialects/postgres/connection-manager.js b/src/dialects/postgres/connection-manager.js index f60b67df9d4e..b6dad3984531 100644 --- a/src/dialects/postgres/connection-manager.js +++ b/src/dialects/postgres/connection-manager.js @@ -117,11 +117,18 @@ class ConnectionManager extends AbstractConnectionManager { 'statement_timeout', // Times out queries after a set time in milliseconds in client end, query would be still running in database end. 'query_timeout', + // Number of milliseconds to wait for connection, default is no timeout. + 'connectionTimeoutMillis', // Terminate any session with an open transaction that has been idle for longer than the specified duration in milliseconds. Added in pg v7.17.0 only supported in postgres >= 10 'idle_in_transaction_session_timeout', + // Maximum wait time for lock requests in milliseconds. Added in pg v8.8.0. + 'lock_timeout', // Postgres allows additional session variables to be configured in the connection string in the `options` param. // see [https://www.postgresql.org/docs/14/libpq-connect.html#LIBPQ-CONNECT-OPTIONS] - 'options' + 'options', + // The stream acts as a user-defined socket factory for postgres. In particular, it enables IAM autentication + // with Google Cloud SQL. see: https://github.com/sequelize/sequelize/issues/16001#issuecomment-1561136388 + 'stream' ])); } @@ -200,6 +207,13 @@ class ConnectionManager extends AbstractConnectionManager { }); }); + // Don't let a Postgres restart (or error) to take down the whole app + connection.on('error', error => { + connection._invalid = true; + debug(`connection error ${error.code || error.message}`); + this.pool.destroy(connection); + }); + let query = ''; if (this.sequelize.options.standardConformingStrings !== false && connection['standard_conforming_strings'] !== 'on') { @@ -240,12 +254,6 @@ class ConnectionManager extends AbstractConnectionManager { this.enumOids.arrayOids.length === 0) { await this._refreshDynamicOIDs(connection); } - // Don't let a Postgres restart (or error) to take down the whole app - connection.on('error', error => { - connection._invalid = true; - debug(`connection error ${error.code || error.message}`); - this.pool.destroy(connection); - }); return connection; } diff --git a/src/dialects/postgres/index.js b/src/dialects/postgres/index.js index eb1cd3e27234..c754d1c0f61a 100644 --- a/src/dialects/postgres/index.js +++ b/src/dialects/postgres/index.js @@ -22,6 +22,14 @@ class PostgresDialect extends AbstractDialect { this.queryGenerator ); } + + canBackslashEscape() { + // postgres can use \ to escape if one of these is true: + // - standard_conforming_strings is off + // - the string is prefixed with E (out of scope for this method) + + return !this.sequelize.options.standardConformingStrings; + } } PostgresDialect.prototype.supports = _.merge( @@ -52,7 +60,8 @@ PostgresDialect.prototype.supports = _.merge( inserts: { onConflictDoNothing: ' ON CONFLICT DO NOTHING', updateOnDuplicate: ' ON CONFLICT DO UPDATE SET', - conflictFields: true + conflictFields: true, + onConflictWhere: true }, NUMERIC: true, ARRAY: true, @@ -65,7 +74,8 @@ PostgresDialect.prototype.supports = _.merge( HSTORE: true, TSVECTOR: true, deferrableConstraints: true, - searchPath: true + searchPath: true, + escapeStringConstants: true } ); diff --git a/src/dialects/postgres/query-generator.js b/src/dialects/postgres/query-generator.js index 7ee3e0b621da..0cf9370ac164 100644 --- a/src/dialects/postgres/query-generator.js +++ b/src/dialects/postgres/query-generator.js @@ -46,14 +46,14 @@ class PostgresQueryGenerator extends AbstractQueryGenerator { const databaseVersion = _.get(this, 'sequelize.options.databaseVersion', 0); if (databaseVersion && semver.gte(databaseVersion, '9.2.0')) { - return `CREATE SCHEMA IF NOT EXISTS ${schema};`; + return `CREATE SCHEMA IF NOT EXISTS ${this.quoteIdentifier(schema)};`; } - return `CREATE SCHEMA ${schema};`; + return `CREATE SCHEMA ${this.quoteIdentifier(schema)};`; } dropSchema(schema) { - return `DROP SCHEMA IF EXISTS ${schema} CASCADE;`; + return `DROP SCHEMA IF EXISTS ${this.quoteIdentifier(schema)} CASCADE;`; } showSchemasQuery() { @@ -124,11 +124,20 @@ class PostgresQueryGenerator extends AbstractQueryGenerator { } showTablesQuery() { - return "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_type LIKE '%TABLE' AND table_name != 'spatial_ref_sys';"; + const schema = this.options.schema || 'public'; + + return `SELECT table_name FROM information_schema.tables WHERE table_schema = ${this.escape(schema)} AND table_type LIKE '%TABLE' AND table_name != 'spatial_ref_sys';`; + } + + tableExistsQuery(tableName) { + const table = tableName.tableName || tableName; + const schema = tableName.schema || 'public'; + + return `SELECT table_name FROM information_schema.tables WHERE table_schema = ${this.escape(schema)} AND table_name = ${this.escape(table)}`; } describeTableQuery(tableName, schema) { - if (!schema) schema = 'public'; + schema = schema || this.options.schema || 'public'; return 'SELECT ' + 'pk.constraint_type as "Constraint",' + @@ -149,7 +158,7 @@ class PostgresQueryGenerator extends AbstractQueryGenerator { 'ON pk.table_schema=c.table_schema ' + 'AND pk.table_name=c.table_name ' + 'AND pk.column_name=c.column_name ' + - `WHERE c.table_name = ${this.escape(tableName)} AND c.table_schema = ${this.escape(schema)} `; + `WHERE c.table_name = ${this.escape(tableName)} AND c.table_schema = ${this.escape(schema)}`; } /** @@ -524,24 +533,26 @@ class PostgresQueryGenerator extends AbstractQueryGenerator { let referencesKey; - if (attribute.references.key) { - referencesKey = this.quoteIdentifiers(attribute.references.key); - } else { - referencesKey = this.quoteIdentifier('id'); - } + if (!options.withoutForeignKeyConstraints) { + if (attribute.references.key) { + referencesKey = this.quoteIdentifiers(attribute.references.key); + } else { + referencesKey = this.quoteIdentifier('id'); + } - sql += ` REFERENCES ${referencesTable} (${referencesKey})`; + sql += ` REFERENCES ${referencesTable} (${referencesKey})`; - if (attribute.onDelete) { - sql += ` ON DELETE ${attribute.onDelete.toUpperCase()}`; - } + if (attribute.onDelete) { + sql += ` ON DELETE ${attribute.onDelete.toUpperCase()}`; + } - if (attribute.onUpdate) { - sql += ` ON UPDATE ${attribute.onUpdate.toUpperCase()}`; - } + if (attribute.onUpdate) { + sql += ` ON UPDATE ${attribute.onUpdate.toUpperCase()}`; + } - if (attribute.references.deferrable) { - sql += ` ${attribute.references.deferrable.toString(this)}`; + if (attribute.references.deferrable) { + sql += ` ${attribute.references.deferrable.toString(this)}`; + } } } @@ -772,7 +783,7 @@ class PostgresQueryGenerator extends AbstractQueryGenerator { values = dataType.toString().match(/^ENUM\(.+\)/)[0]; } - let sql = `CREATE TYPE ${enumName} AS ${values};`; + let sql = `DO ${this.escape(`BEGIN CREATE TYPE ${enumName} AS ${values}; EXCEPTION WHEN duplicate_object THEN null; END`)};`; if (!!options && options.force === true) { sql = this.pgEnumDrop(tableName, attr) + sql; } @@ -865,6 +876,8 @@ class PostgresQueryGenerator extends AbstractQueryGenerator { 'tc.table_name as table_name,' + 'tc.table_schema as table_schema,' + 'tc.table_catalog as table_catalog,' + + 'tc.initially_deferred as initially_deferred,' + + 'tc.is_deferrable as is_deferrable,' + 'kcu.column_name as column_name,' + 'ccu.table_schema AS referenced_table_schema,' + 'ccu.table_catalog AS referenced_table_catalog,' + diff --git a/src/dialects/postgres/query-interface.js b/src/dialects/postgres/query-interface.js index 19a07e467564..b13fe3ec25f8 100644 --- a/src/dialects/postgres/query-interface.js +++ b/src/dialects/postgres/query-interface.js @@ -4,6 +4,7 @@ const DataTypes = require('../../data-types'); const QueryTypes = require('../../query-types'); const { QueryInterface } = require('../abstract/query-interface'); const Utils = require('../../utils'); +const Deferrable = require('../../deferrable'); /** * The interface that Sequelize uses to talk with Postgres database @@ -156,9 +157,19 @@ class PostgresQueryInterface extends QueryInterface { // postgres needs some special treatment as those field names returned are all lowercase // in order to keep same result with other dialects. - const query = this.queryGenerator.getForeignKeyReferencesQuery(table.tableName || table, this.sequelize.config.database); + const query = this.queryGenerator.getForeignKeyReferencesQuery(table.tableName || table, this.sequelize.config.database, table.schema); const result = await this.sequelize.query(query, queryOptions); - return result.map(Utils.camelizeObjectKeys); + + return result.map(fkMeta => { + const { initiallyDeferred, isDeferrable, ...remaining } = Utils.camelizeObjectKeys(fkMeta); + + return { + ...remaining, + deferrable: isDeferrable === 'NO' ? Deferrable.NOT + : initiallyDeferred === 'NO' ? Deferrable.INITIALLY_IMMEDIATE + : Deferrable.INITIALLY_DEFERRED + }; + }); } /** diff --git a/src/dialects/postgres/query.js b/src/dialects/postgres/query.js index 7b15eb8924cd..70e330becf1d 100644 --- a/src/dialects/postgres/query.js +++ b/src/dialects/postgres/query.js @@ -85,6 +85,8 @@ class Query extends AbstractQuery { || /Unable to set non-blocking to true/i.test(error) || /SSL SYSCALL error: EOF detected/i.test(error) || /Local: Authentication failure/i.test(error) + // https://github.com/sequelize/sequelize/pull/15144 + || error.message === 'Query read timeout' ) { connection._invalid = true; } diff --git a/src/dialects/snowflake/query-generator.js b/src/dialects/snowflake/query-generator.js index 91851c22c45d..6db85321213a 100644 --- a/src/dialects/snowflake/query-generator.js +++ b/src/dialects/snowflake/query-generator.js @@ -32,7 +32,7 @@ const FOREIGN_KEY_FIELDS = [ * @private */ const SNOWFLAKE_RESERVED_WORDS = 'account,all,alter,and,any,as,between,by,case,cast,check,column,connect,connections,constraint,create,cross,current,current_date,current_time,current_timestamp,current_user,database,delete,distinct,drop,else,exists,false,following,for,from,full,grant,group,gscluster,having,ilike,in,increment,inner,insert,intersect,into,is,issue,join,lateral,left,like,localtime,localtimestamp,minus,natural,not,null,of,on,or,order,organization,qualify,regexp,revoke,right,rlike,row,rows,sample,schema,select,set,some,start,table,tablesample,then,to,trigger,true,try_cast,union,unique,update,using,values,view,when,whenever,where,with'.split(','); - + const typeWithoutDefault = new Set(['BLOB', 'TEXT', 'GEOMETRY', 'JSON']); class SnowflakeQueryGenerator extends AbstractQueryGenerator { @@ -170,6 +170,18 @@ class SnowflakeQueryGenerator extends AbstractQueryGenerator { ]); } + tableExistsQuery(table) { + const tableName = table.tableName || table; + const schema = table.schema; + + return Utils.joinSQLFragments([ + 'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = \'BASE TABLE\'', + `AND TABLE_SCHEMA = ${schema !== undefined ? this.escape(schema) : 'CURRENT_SCHEMA()'}`, + `AND TABLE_NAME = ${this.escape(tableName)}`, + ';' + ]); + } + addColumnQuery(table, key, dataType) { return Utils.joinSQLFragments([ 'ALTER TABLE', diff --git a/src/dialects/sqlite/index.js b/src/dialects/sqlite/index.js index d866de37bcae..7b04af9fc92a 100644 --- a/src/dialects/sqlite/index.js +++ b/src/dialects/sqlite/index.js @@ -35,7 +35,8 @@ SqliteDialect.prototype.supports = _.merge( inserts: { ignoreDuplicates: ' OR IGNORE', updateOnDuplicate: ' ON CONFLICT DO UPDATE SET', - conflictFields: true + conflictFields: true, + onConflictWhere: true }, index: { using: false, diff --git a/src/dialects/sqlite/query-generator.js b/src/dialects/sqlite/query-generator.js index e0dba2098a27..55bd86445e1c 100644 --- a/src/dialects/sqlite/query-generator.js +++ b/src/dialects/sqlite/query-generator.js @@ -457,7 +457,7 @@ class SQLiteQueryGenerator extends MySqlQueryGenerator { /** * Generates an SQL query that returns all foreign keys of a table. * - * @param {string} tableName The name of the table. + * @param {TableName} tableName The name of the table. * @returns {string} The generated sql query. * @private */ @@ -465,6 +465,10 @@ class SQLiteQueryGenerator extends MySqlQueryGenerator { return `PRAGMA foreign_key_list(${this.quoteTable(this.addSchema(tableName))})`; } + tableExistsQuery(tableName) { + return `SELECT name FROM sqlite_master WHERE type='table' AND name=${this.escape(this.addSchema(tableName))};`; + } + /** * Quote identifier in sql clause * diff --git a/src/dialects/sqlite/query.js b/src/dialects/sqlite/query.js index 9518b91ec8e1..6cd118a93644 100644 --- a/src/dialects/sqlite/query.js +++ b/src/dialects/sqlite/query.js @@ -10,6 +10,15 @@ const { logger } = require('../../utils/logger'); const debug = logger.debugContext('sql:sqlite'); +// sqlite3 currently ignores bigint values, so we have to translate to string for now +// There's a WIP here: https://github.com/TryGhost/node-sqlite3/pull/1501 +function stringifyIfBigint(value) { + if (typeof value === 'bigint') { + return value.toString(); + } + + return value; +} class Query extends AbstractQuery { getInsertIdField() { @@ -244,6 +253,17 @@ class Query extends AbstractQuery { } if (!parameters) parameters = []; + + if (_.isPlainObject(parameters)) { + const newParameters = Object.create(null); + for (const key of Object.keys(parameters)) { + newParameters[`${key}`] = stringifyIfBigint(parameters[key]); + } + parameters = newParameters; + } else { + parameters = parameters.map(stringifyIfBigint); + } + conn[method](sql, parameters, afterExecute); return null; diff --git a/src/dialects/sqlite/sqlite-utils.ts b/src/dialects/sqlite/sqlite-utils.ts new file mode 100644 index 000000000000..1fdc62c2983e --- /dev/null +++ b/src/dialects/sqlite/sqlite-utils.ts @@ -0,0 +1,12 @@ +import type { Sequelize } from '../../sequelize.js'; +import type { QueryOptions } from '../abstract/query-interface.js'; + +export async function withSqliteForeignKeysOff(sequelize: Sequelize, options: QueryOptions, cb: () => Promise): Promise { + try { + await sequelize.query('PRAGMA foreign_keys = OFF', options); + + return await cb(); + } finally { + await sequelize.query('PRAGMA foreign_keys = ON', options); + } +} diff --git a/src/hooks.d.ts b/src/hooks.d.ts index bd3bc9355cde..50b399802af0 100644 --- a/src/hooks.d.ts +++ b/src/hooks.d.ts @@ -15,6 +15,7 @@ import { AbstractQuery } from './dialects/abstract/query'; import { QueryOptions } from './dialects/abstract/query-interface'; import { Config, Options, Sequelize, SyncOptions } from './sequelize'; import { DeepWriteable } from './utils'; +import { Connection, GetConnectionOptions } from './dialects/abstract/connection-manager'; export type HookReturn = Promise | void; @@ -67,8 +68,8 @@ export interface ModelHooks { export interface SequelizeHooks< M extends Model = Model, - TAttributes = any, - TCreationAttributes = TAttributes + TAttributes extends {} = any, + TCreationAttributes extends {} = TAttributes > extends ModelHooks { beforeDefine(attributes: ModelAttributes, options: ModelOptions): void; afterDefine(model: ModelType): void; @@ -76,6 +77,8 @@ export interface SequelizeHooks< afterInit(sequelize: Sequelize): void; beforeConnect(config: DeepWriteable): HookReturn; afterConnect(connection: unknown, config: Config): HookReturn; + beforePoolAcquire(config: GetConnectionOptions): HookReturn; + afterPoolAcquire(connection: Connection, config: GetConnectionOptions): HookReturn; beforeDisconnect(connection: unknown): HookReturn; afterDisconnect(connection: unknown): HookReturn; } diff --git a/src/hooks.js b/src/hooks.js index 69602a048b4d..b3c4befce09c 100644 --- a/src/hooks.js +++ b/src/hooks.js @@ -43,6 +43,8 @@ const hookTypes = { afterConnect: { params: 2, noModel: true }, beforeDisconnect: { params: 1, noModel: true }, afterDisconnect: { params: 1, noModel: true }, + beforePoolAcquire: { params: 1, noModel: true }, + afterPoolAcquire: { params: 2, noModel: true }, beforeSync: { params: 1 }, afterSync: { params: 1 }, beforeBulkSync: { params: 1 }, @@ -541,6 +543,24 @@ exports.applyTo = applyTo; * @memberof Sequelize */ +/** + * A hook that is run before a connection to the pool + * + * @param {string} name + * @param {Function} fn A callback function that is called with config passed to connection + * @name beforePoolAcquire + * @memberof Sequelize + */ + +/** + * A hook that is run after a connection to the pool + * + * @param {string} name + * @param {Function} fn A callback function that is called with the connection object and the config passed to connection + * @name afterPoolAcquire + * @memberof Sequelize + */ + /** * A hook that is run before a connection is disconnected * diff --git a/src/model-manager.d.ts b/src/model-manager.d.ts index 41e72dae6636..248c11f7c965 100644 --- a/src/model-manager.d.ts +++ b/src/model-manager.d.ts @@ -10,6 +10,16 @@ export class ModelManager { public addModel(model: T): T; public removeModel(model: ModelType): void; public getModel(against: unknown, options?: { attribute?: string }): typeof Model; + public findModel(callback: (model: typeof Model) => boolean): typeof Model | undefined + + /** + * Returns an array that lists every model, sorted in order + * of foreign key references: The first model is a model that is depended upon, + * the last model is a model that is not depended upon. + * + * If there is a cyclic dependency, this returns null. + */ + public getModelsTopoSortedByForeignKey(): ModelType[] | null; } export default ModelManager; diff --git a/src/model-manager.js b/src/model-manager.js index 3f36edcf1e3e..69b753b32b88 100644 --- a/src/model-manager.js +++ b/src/model-manager.js @@ -30,27 +30,24 @@ class ModelManager { return this.models.find(model => model[options.attribute] === against); } + findModel(callback) { + return this.models.find(callback); + } + get all() { return this.models; } /** - * Iterate over Models in an order suitable for e.g. creating tables. - * Will take foreign key constraints into account so that dependencies are visited before dependents. + * Returns an array that lists every model, sorted in order + * of foreign key references: The first model is a model that is depended upon, + * the last model is a model that is not depended upon. * - * @param {Function} iterator method to execute on each model - * @param {object} [options] iterator options - * @private + * If there is a cyclic dependency, this returns null. */ - forEachModel(iterator, options) { - const models = {}; + getModelsTopoSortedByForeignKey() { + const models = new Map(); const sorter = new Toposort(); - let sorted; - let dep; - - options = _.defaults(options || {}, { - reverse: true - }); for (const model of this.models) { let deps = []; @@ -60,14 +57,14 @@ class ModelManager { tableName = `${tableName.schema}.${tableName.tableName}`; } - models[tableName] = model; + models.set(tableName, model); for (const attrName in model.rawAttributes) { if (Object.prototype.hasOwnProperty.call(model.rawAttributes, attrName)) { const attribute = model.rawAttributes[attrName]; if (attribute.references) { - dep = attribute.references.model; + let dep = attribute.references.model; if (_.isObject(dep)) { dep = `${dep.schema}.${dep.tableName}`; @@ -83,12 +80,50 @@ class ModelManager { sorter.add(tableName, deps); } - sorted = sorter.sort(); + let sorted; + try { + sorted = sorter.sort(); + } catch (e) { + if (!e.message.startsWith('Cyclic dependency found.')) { + throw e; + } + + return null; + } + + return sorted + .map(modelName => { + return models.get(modelName); + }) + .filter(Boolean); + } + + /** + * Iterate over Models in an order suitable for e.g. creating tables. + * Will take foreign key constraints into account so that dependencies are visited before dependents. + * + * @param {Function} iterator method to execute on each model + * @param {object} options + * @private + * + * @deprecated + */ + forEachModel(iterator, options) { + const sortedModels = this.getModelsTopoSortedByForeignKey(); + if (sortedModels == null) { + throw new Error('Cyclic dependency found.'); + } + + options = _.defaults(options || {}, { + reverse: true + }); + if (options.reverse) { - sorted = sorted.reverse(); + sortedModels.reverse(); } - for (const name of sorted) { - iterator(models[name], name); + + for (const model of sortedModels) { + iterator(model); } } } diff --git a/src/model.d.ts b/src/model.d.ts index 7155761f8770..7ab36db85b7f 100644 --- a/src/model.d.ts +++ b/src/model.d.ts @@ -10,6 +10,9 @@ import { Col, Fn, Literal, Where, MakeNullishOptional, AnyFunction, Cast, Json } import { LOCK, Transaction, Op, Optional } from './index'; import { SetRequired } from './utils/set-required'; +// Backport of https://github.com/sequelize/sequelize/blob/a68b439fb3ea748d3f3d37356d9fe610f86184f6/src/utils/index.ts#L85 +export type AllowReadonlyArray = T | readonly T[]; + export interface Logging { /** * A function that gets executed while running the query to log the sql. @@ -771,7 +774,7 @@ export interface FindOptions * A list of associations to eagerly load using a left join (a single association is also supported). Supported is either * `{ include: Model1 }`, `{ include: [ Model1, Model2, ...]}`, `{ include: [{ model: Model1, as: 'Alias' }]}` or * `{ include: [{ all: true }]}`. - * If your association are set up with an `as` (eg. `X.hasMany(Y, { as: 'Z }`, you need to specify Z in + * If your association are set up with an `as` (eg. `X.hasMany(Y, { as: 'Z' }`, you need to specify Z in * the as attribute when eager loading Y). */ include?: Includeable | Includeable[]; @@ -1019,6 +1022,12 @@ export interface UpsertOptions extends Logging, Transactionab * Run validations before the row is inserted */ validate?: boolean; + /** + * An optional parameter that specifies a where clause for the `ON CONFLICT` part of the query + * (in particular: for applying to partial unique indexes). + * Only supported in Postgres >= 9.5 and SQLite >= 3.24.0 + */ + conflictWhere?: WhereOptions; /** * Optional override for the conflict fields in the ON CONFLICT part of the query. * Only supported in Postgres >= 9.5 and SQLite >= 3.24.0 @@ -1069,6 +1078,17 @@ export interface BulkCreateOptions extends Logging, Transacti * Return all columns or only the specified columns for the affected rows (only for postgres) */ returning?: boolean | (keyof TAttributes)[]; + /** + * An optional parameter to specify a where clause for partial unique indexes + * (note: `ON CONFLICT WHERE` not `ON CONFLICT DO UPDATE WHERE`). + * Only supported in Postgres >= 9.5 and sqlite >= 9.5 + */ + conflictWhere?: WhereOptions; + /** + * Optional override for the conflict fields in the ON CONFLICT part of the query. + * Only supported in Postgres >= 9.5 and SQLite >= 3.24.0 + */ + conflictAttributes?: Array; } /** @@ -1284,6 +1304,11 @@ export interface SaveOptions extends Logging, Transactionable * @default false */ omitNull?: boolean; + + /** + * Return the affected rows (only for postgres) + */ + returning?: boolean | Array; } /** @@ -1660,7 +1685,7 @@ export type ModelAttributes = { /** * Possible types for primary keys */ -export type Identifier = number | string | Buffer; +export type Identifier = number | bigint | string | Buffer; /** * Options for model definition @@ -1863,6 +1888,11 @@ export abstract class Model6]: make this a non-exported symbol (same as the one in hooks.d.ts) + /** + * Object that contains underlying model data + */ + dataValues: TModelAttributes; + /** * A similar dummy variable that doesn't exist on the real object. Do not * try to access this in real code. @@ -2468,58 +2498,66 @@ export abstract class Model; /** - * Increments a single field. - */ - public static increment( - this: ModelStatic, - field: keyof Attributes, - options: IncrementDecrementOptionsWithBy> - ): Promise; - - /** - * Increments multiple fields by the same value. + * Increments the value of one or more attributes. + * + * The increment is done using a `SET column = column + X WHERE foo = 'bar'` query. + * + * @example increment number by 1 + * ```javascript + * Model.increment('number', { where: { foo: 'bar' }); + * ``` + * + * @example increment number and count by 2 + * ```javascript + * Model.increment(['number', 'count'], { by: 2, where: { foo: 'bar' } }); + * ``` + * + * @example increment answer by 42, and decrement tries by 1 + * ```javascript + * // `by` cannot be used, as each attribute specifies its own value + * Model.increment({ answer: 42, tries: -1}, { where: { foo: 'bar' } }); + * ``` + * + * @param fields If a string is provided, that column is incremented by the + * value of `by` given in options. If an array is provided, the same is true for each column. + * If an object is provided, each key is incremented by the corresponding value, `by` is ignored. + * + * @returns an array of affected rows or with affected count if `options.returning` is true, whenever supported by dialect */ - public static increment( + static increment( this: ModelStatic, - fields: ReadonlyArray>, + fields: AllowReadonlyArray>, options: IncrementDecrementOptionsWithBy> - ): Promise; - - /** - * Increments multiple fields by different values. - */ - public static increment( + ): Promise<[affectedRows: M[], affectedCount?: number]>; + static increment( this: ModelStatic, fields: { [key in keyof Attributes]?: number }, options: IncrementDecrementOptions> - ): Promise; - - /** - * Decrements a single field. - */ - public static decrement( - this: ModelStatic, - field: keyof Attributes, - options: IncrementDecrementOptionsWithBy> - ): Promise; + ): Promise<[affectedRows: M[], affectedCount?: number]>; /** - * Decrements multiple fields by the same value. + * Decrements the value of one or more attributes. + * + * Works like {@link Model.increment} + * + * @param fields If a string is provided, that column is incremented by the + * value of `by` given in options. If an array is provided, the same is true for each column. + * If an object is provided, each key is incremented by the corresponding value, `by` is ignored. + * + * @returns an array of affected rows or with affected count if `options.returning` is true, whenever supported by dialect + * + * @since 4.36.0 */ - public static decrement( + static decrement( this: ModelStatic, - fields: (keyof Attributes)[], + fields: AllowReadonlyArray>, options: IncrementDecrementOptionsWithBy> - ): Promise; - - /** - * Decrements multiple fields by different values. - */ - public static decrement( + ): Promise<[affectedRows: M[], affectedCount?: number]>; + static decrement( this: ModelStatic, fields: { [key in keyof Attributes]?: number }, options: IncrementDecrementOptions> - ): Promise; + ): Promise<[affectedRows: M[], affectedCount?: number]>; /** * Run a describe query on the table. The result will be return to the listener as a hash of attributes and @@ -3249,7 +3287,7 @@ export abstract class Model = new () => Model; +export type ModelType = new () => Model; type NonConstructorKeys = ({[P in keyof T]: T[P] extends new () => any ? never : P })[keyof T]; type NonConstructor = Pick>; @@ -3257,7 +3295,7 @@ type NonConstructor = Pick>; /** @deprecated use ModelStatic */ export type ModelCtor = ModelStatic; -export type ModelDefined = ModelStatic>; +export type ModelDefined = ModelStatic>; // remove the existing constructor that tries to return `Model<{},{}>` which would be incompatible with models that have typing defined & replace with proper constructor. export type ModelStatic = NonConstructor & { new(): M }; @@ -3433,15 +3471,15 @@ export type InferCreationAttributes< * - Excluded manually using {@link InferAttributesOptions#omit} */ type InternalInferAttributeKeysFromFields> = - // functions are always excluded - M[Key] extends AnyFunction ? never // fields inherited from Model are all excluded - : Key extends keyof Model ? never + Key extends keyof Model ? never + // functions are always excluded + : M[Key] extends AnyFunction ? never // fields branded with NonAttribute are excluded : IsBranded extends true ? never // check 'omit' option is provided & exclude those listed in it : Options['omit'] extends string ? (Key extends Options['omit'] ? never : Key) - : Key + : Key; // in v7, we should be able to drop InferCreationAttributes and InferAttributes, // resolving this confusion. diff --git a/src/model.js b/src/model.js index 310304eb6005..368590a84e8a 100644 --- a/src/model.js +++ b/src/model.js @@ -1338,19 +1338,30 @@ class Model { if (options.hooks) { await this.runHooks('beforeSync', options); } + + const tableName = this.getTableName(options); + + let tableExists; if (options.force) { await this.drop(options); + tableExists = false; + } else { + tableExists = await this.queryInterface.tableExists(tableName, options); } - const tableName = this.getTableName(options); - - await this.queryInterface.createTable(tableName, attributes, options, this); + if (!tableExists) { + await this.queryInterface.createTable(tableName, attributes, options, this); + } else { + // enums are always updated, even if alter is not set. createTable calls it too. + await this.queryInterface.ensureEnums(tableName, attributes, options, this); + } - if (options.alter) { + if (tableExists && options.alter) { const tableInfos = await Promise.all([ this.queryInterface.describeTable(tableName, options), this.queryInterface.getForeignKeyReferencesForTable(tableName, options) ]); + const columns = tableInfos[0]; // Use for alter foreign keys const foreignKeyReferences = tableInfos[1]; @@ -1393,13 +1404,15 @@ class Model { } } } + await this.queryInterface.changeColumn(tableName, columnName, currentAttribute, options); } } } - let indexes = await this.queryInterface.showIndex(tableName, options); - indexes = this._indexes.filter(item1 => - !indexes.some(item2 => item1.name === item2.name) + + const existingIndexes = await this.queryInterface.showIndex(tableName, options); + const missingIndexes = this._indexes.filter(item1 => + !existingIndexes.some(item2 => item1.name === item2.name) ).sort((index1, index2) => { if (this.sequelize.options.dialect === 'postgres') { // move concurrent indexes to the bottom to avoid weird deadlocks @@ -1410,7 +1423,7 @@ class Model { return 0; }); - for (const index of indexes) { + for (const index of missingIndexes) { await this.queryInterface.addIndex(tableName, { ...options, ...index }); } @@ -1690,7 +1703,7 @@ class Model { * @param {Array} [options.attributes.include] Select all the attributes of the model, plus some additional ones. Useful for aggregations, e.g. `{ attributes: { include: [[sequelize.fn('COUNT', sequelize.col('id')), 'total']] }` * @param {Array} [options.attributes.exclude] Select all the attributes of the model, except some few. Useful for security purposes e.g. `{ attributes: { exclude: ['password'] } }` * @param {boolean} [options.paranoid=true] If true, only non-deleted records will be returned. If false, both deleted and non-deleted records will be returned. Only applies if `options.paranoid` is true for the model. - * @param {Array} [options.include] A list of associations to eagerly load using a left join. Supported is either `{ include: [ Model1, Model2, ...]}` or `{ include: [{ model: Model1, as: 'Alias' }]}` or `{ include: ['Alias']}`. If your association are set up with an `as` (eg. `X.hasMany(Y, { as: 'Z }`, you need to specify Z in the as attribute when eager loading Y). + * @param {Array} [options.include] A list of associations to eagerly load using a left join. Supported is either `{ include: [ Model1, Model2, ...]}` or `{ include: [{ model: Model1, as: 'Alias' }]}` or `{ include: ['Alias']}`. If your association are set up with an `as` (eg. `X.hasMany(Y, { as: 'Z' }`, you need to specify Z in the as attribute when eager loading Y). * @param {Model} [options.include[].model] The model you want to eagerly load * @param {string} [options.include[].as] The alias of the relation, in case the model you want to eagerly load is aliased. For `hasOne` / `belongsTo`, this should be the singular name, and for `hasMany`, it should be the plural * @param {Association} [options.include[].association] The association you want to eagerly load. (This can be used instead of providing a model/as pair) @@ -1721,6 +1734,7 @@ class Model { * @param {string} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only) * @param {boolean|Error} [options.rejectOnEmpty=false] Throws an error when no records found * @param {boolean} [options.dotNotation] Allows including tables having the same attribute/column names - which have a dot in them. + * @param {boolean} [options.nest=false] If true, transforms objects with `.` separated property names into nested objects. * * @see * {@link Sequelize#query} @@ -1745,6 +1759,14 @@ class Model { tableNames[this.getTableName(options)] = true; options = Utils.cloneDeep(options); + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + _.defaults(options, { hooks: true }); // set rejectOnEmpty option, defaults to model options @@ -1902,10 +1924,10 @@ class Model { /** * Search for a single instance by its primary key._ * - * @param {number|string|Buffer} param The value of the desired instance's primary key. - * @param {object} [options] find options - * @param {Transaction} [options.transaction] Transaction to run query under - * @param {string} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only) + * @param {number|bigint|string|Buffer} param The value of the desired instance's primary key. + * @param {object} [options] find options + * @param {Transaction} [options.transaction] Transaction to run query under + * @param {string} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only) * * @see * {@link Model.findAll} for a full explanation of options, Note that options.where is not supported. @@ -1920,7 +1942,7 @@ class Model { options = Utils.cloneDeep(options) || {}; - if (typeof param === 'number' || typeof param === 'string' || Buffer.isBuffer(param)) { + if (typeof param === 'number' || typeof param === 'bigint' || typeof param === 'string' || Buffer.isBuffer(param)) { options.where = { [this.primaryKeyAttribute]: param }; @@ -1951,6 +1973,14 @@ class Model { } options = Utils.cloneDeep(options); + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + if (options.limit === undefined) { const uniqueSingleColumns = _.chain(this.uniqueKeys).values().filter(c => c.fields.length === 1).map('column').value(); @@ -2061,6 +2091,15 @@ class Model { static async count(options) { options = Utils.cloneDeep(options); options = _.defaults(options, { hooks: true }); + + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + options.raw = true; if (options.hooks) { await this.runHooks('beforeCount', options); @@ -2507,6 +2546,14 @@ class Model { ...Utils.cloneDeep(options) }; + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + const createdAtAttr = this._timestampAttributes.createdAt; const updatedAtAttr = this._timestampAttributes.updatedAt; const hasPrimary = this.primaryKeyField in values || this.primaryKeyAttribute in values; @@ -2585,6 +2632,7 @@ class Model { * @param {boolean} [options.individualHooks=false] Run before / after create hooks for each individual Instance? BulkCreate hooks will still be run if options.hooks is true. * @param {boolean} [options.ignoreDuplicates=false] Ignore duplicate values for primary keys? (not supported by MSSQL or Postgres < 9.5) * @param {Array} [options.updateOnDuplicate] Fields to update if row key already exists (on duplicate key update)? (only supported by MySQL, MariaDB, SQLite >= 3.24.0 & Postgres >= 9.5). + * @param {Array} [options.conflictAttributes] Optional override for the conflict fields in the ON CONFLICT part of the query. Only supported in Postgres >= 9.5 and SQLite >= 3.24.0 * @param {Transaction} [options.transaction] Transaction to run query under * @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql. * @param {boolean} [options.benchmark=false] Pass query execution time in milliseconds as second argument to logging function (options.logging). @@ -2602,6 +2650,14 @@ class Model { const now = Utils.now(this.sequelize.options.dialect); options = Utils.cloneDeep(options); + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + options.model = this; if (!options.includeValidated) { @@ -2630,8 +2686,8 @@ class Model { options.returning = true; } } - - if (options.ignoreDuplicates && ['mssql', 'db2'].includes(dialect)) { + if (options.ignoreDuplicates && !this.sequelize.dialect.supports.inserts.ignoreDuplicates && + !this.sequelize.dialect.supports.inserts.onConflictDoNothing) { throw new Error(`${dialect} does not support the ignoreDuplicates option.`); } if (options.updateOnDuplicate && (dialect !== 'mysql' && dialect !== 'mariadb' && dialect !== 'sqlite' && dialect !== 'postgres')) { @@ -2762,23 +2818,29 @@ class Model { if (options.updateOnDuplicate) { options.updateOnDuplicate = options.updateOnDuplicate.map(attr => model.rawAttributes[attr].field || attr); - const upsertKeys = []; + if (options.conflictAttributes) { + options.upsertKeys = options.conflictAttributes.map( + attrName => model.rawAttributes[attrName].field || attrName + ); + } else { + const upsertKeys = []; - for (const i of model._indexes) { - if (i.unique && !i.where) { // Don't infer partial indexes - upsertKeys.push(...i.fields); + for (const i of model._indexes) { + if (i.unique && !i.where) { // Don't infer partial indexes + upsertKeys.push(...i.fields); + } } - } - const firstUniqueKey = Object.values(model.uniqueKeys).find(c => c.fields.length > 0); + const firstUniqueKey = Object.values(model.uniqueKeys).find(c => c.fields.length > 0); - if (firstUniqueKey && firstUniqueKey.fields) { - upsertKeys.push(...firstUniqueKey.fields); - } + if (firstUniqueKey && firstUniqueKey.fields) { + upsertKeys.push(...firstUniqueKey.fields); + } - options.upsertKeys = upsertKeys.length > 0 - ? upsertKeys - : Object.values(model.primaryKeys).map(x => x.field); + options.upsertKeys = upsertKeys.length > 0 + ? upsertKeys + : Object.values(model.primaryKeys).map(x => x.field); + } } // Map returning attributes to fields @@ -2864,7 +2926,7 @@ class Model { if (include.association.through.model.rawAttributes[attr]._autoGenerated || attr === include.association.foreignKey || attr === include.association.otherKey || - typeof associationInstance[include.association.through.model.name][attr] === undefined) { + typeof associationInstance[include.association.through.model.name][attr] === 'undefined') { continue; } values[attr] = associationInstance[include.association.through.model.name][attr]; @@ -2958,6 +3020,14 @@ class Model { static async destroy(options) { options = Utils.cloneDeep(options); + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + this._injectScope(options); if (!options || !(options.where || options.truncate)) { @@ -3048,6 +3118,14 @@ class Model { ...options }; + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + options.type = QueryTypes.RAW; options.model = this; @@ -3113,6 +3191,14 @@ class Model { static async update(values, options) { options = Utils.cloneDeep(options); + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + this._injectScope(options); this._optionsMustContainWhere(options); @@ -3903,6 +3989,15 @@ class Model { } options = Utils.cloneDeep(options); + + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + options = _.defaults(options, { hooks: true, validate: true @@ -4116,7 +4211,7 @@ class Model { if (include.association.through.model.rawAttributes[attr]._autoGenerated || attr === include.association.foreignKey || attr === include.association.otherKey || - typeof instance[include.association.through.model.name][attr] === undefined) { + typeof instance[include.association.through.model.name][attr] === 'undefined') { continue; } values0[attr] = instance[include.association.through.model.name][attr]; @@ -4223,6 +4318,15 @@ class Model { if (Array.isArray(options)) options = { fields: options }; options = Utils.cloneDeep(options); + + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + const setOptions = Utils.cloneDeep(options); setOptions.attributes = options.fields; this.set(values, setOptions); @@ -4257,6 +4361,14 @@ class Model { ...options }; + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + // Run before hook if (options.hooks) { await this.constructor.runHooks('beforeDestroy', this, options); @@ -4326,6 +4438,14 @@ class Model { ...options }; + // Add CLS transaction + if (options.transaction === undefined && this.sequelize.constructor._cls) { + const t = this.sequelize.constructor._cls.get('transaction'); + if (t) { + options.transaction = t; + } + } + // Run before hook if (options.hooks) { await this.constructor.runHooks('beforeRestore', this, options); @@ -4508,6 +4628,7 @@ class Model { * @param {Model} [options.through.model] The model used to join both sides of the N:M association. * @param {object} [options.through.scope] A key/value set that will be used for association create and find defaults on the through model. (Remember to add the attributes to the through model) * @param {boolean} [options.through.unique=true] If true a unique key will be generated from the foreign keys used (might want to turn this off and create specific unique keys when using scopes) + * @param {boolean} [options.through.paranoid=false] If true the generated join table will be paranoid * @param {string|object} [options.as] The alias of this association. If you provide a string, it should be plural, and will be singularized using node.inflection. If you want to control the singular version yourself, provide an object with `plural` and `singular` keys. See also the `name` option passed to `sequelize.define`. If you create multiple associations between the same tables, you should provide an alias to be able to distinguish between them. If you provide an alias when creating the association, you should provide the same alias when eager loading and when getting associated models. Defaults to the pluralized name of target * @param {string|object} [options.foreignKey] The name of the foreign key in the join table (representing the source model) or an object representing the type definition for the foreign column (see `Sequelize.define` for syntax). When using an object, you can add a `name` property to set the name of the column. Defaults to the name of source + primary key of source * @param {string|object} [options.otherKey] The name of the foreign key in the join table (representing the target model) or an object representing the type definition for the other column (see `Sequelize.define` for syntax). When using an object, you can add a `name` property to set the name of the column. Defaults to the name of target + primary key of target diff --git a/src/sequelize.d.ts b/src/sequelize.d.ts index 1ba1cfd1c8b0..8f28ef43cc6d 100644 --- a/src/sequelize.d.ts +++ b/src/sequelize.d.ts @@ -1,3 +1,4 @@ +import type { Options as RetryAsPromisedOptions } from 'retry-as-promised'; import { HookReturn, Hooks, SequelizeHooks } from './hooks'; import { ValidationOptions } from './instance-validator'; import { @@ -29,7 +30,9 @@ import QueryTypes = require('./query-types'); import { Transaction, TransactionOptions } from './transaction'; import { Op } from './index'; import { Cast, Col, DeepWriteable, Fn, Json, Literal, Where } from './utils'; -import { ConnectionManager } from './dialects/abstract/connection-manager'; +import { Connection, ConnectionManager, GetConnectionOptions } from './dialects/abstract/connection-manager'; + +export type RetryOptions = RetryAsPromisedOptions; /** * Additional options for table altering during sync @@ -169,12 +172,7 @@ export interface Config { }; } -export type Dialect = 'mysql' | 'postgres' | 'sqlite' | 'mariadb' | 'mssql' | 'db2' | 'snowflake'; - -export interface RetryOptions { - match?: (RegExp | string | Function)[]; - max?: number; -} +export type Dialect = 'mysql' | 'postgres' | 'sqlite' | 'mariadb' | 'mssql' | 'db2' | 'snowflake' | 'oracle'; /** * Options for the constructor of Sequelize main class @@ -400,6 +398,13 @@ export interface Options extends Logging { * If defined the connection will use the provided schema instead of the default ("public"). */ schema?: string; + + /** + * Sequelize had to introduce a breaking change to fix vulnerability CVE-2023-22578. + * This option allows you to revert to the old behavior (unsafe-legacy), or to opt in to the new behavior (escape). + * The default behavior throws an error to warn you about the change (throw). + */ + attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy'; } export interface QueryOptionsTransactionRequired { } @@ -715,6 +720,26 @@ export class Sequelize extends Hooks { public static afterDisconnect(name: string, fn: (connection: unknown) => void): void; public static afterDisconnect(fn: (connection: unknown) => void): void; + + /** + * A hook that is run before attempting to acquire a connection from the pool + * + * @param name + * @param fn A callback function that is called with options + */ + public static beforePoolAcquire(name: string, fn: (options: GetConnectionOptions) => void): void; + public static beforePoolAcquire(fn: (options: GetConnectionOptions) => void): void; + + /** + * A hook that is run after successfully acquiring a connection from the pool + * + * @param name + * @param fn A callback function that is called with options + */ + public static afterPoolAcquire(name: string, fn: (connection: Connection, options: GetConnectionOptions) => void): void; + public static afterPoolAcquire(fn: (connection: Connection, options: GetConnectionOptions) => void): void; + + /** * A hook that is run before a find (select) query, after any { include: {all: ...} } options are expanded * diff --git a/src/sequelize.js b/src/sequelize.js index e424a9a2b2d2..3098dd0c81ea 100644 --- a/src/sequelize.js +++ b/src/sequelize.js @@ -3,7 +3,7 @@ const url = require('url'); const path = require('path'); const pgConnectionString = require('pg-connection-string'); -const retry = require('retry-as-promised'); +const retry = require('retry-as-promised').default; const _ = require('lodash'); const Utils = require('./utils'); @@ -26,6 +26,7 @@ const { BelongsTo } = require('./associations/belongs-to'); const HasOne = require('./associations/has-one'); const { BelongsToMany } = require('./associations/belongs-to-many'); const { HasMany } = require('./associations/has-many'); +const { withSqliteForeignKeysOff } = require('./dialects/sqlite/sqlite-utils'); const { injectReplacements } = require('./utils/sql'); /** @@ -96,6 +97,10 @@ class Sequelize { * // - default: false * native: true, * + * // A flag that defines if connection should be over ssl or not + * // - default: undefined + * ssl: true, + * * // Specify options, which are used when sequelize.define is called. * // The following example: * // define: { timestamps: false } @@ -155,6 +160,7 @@ class Sequelize { * @param {boolean} [options.benchmark=false] Pass query execution time in milliseconds as second argument to logging function (options.logging). * @param {boolean} [options.omitNull=false] A flag that defines if null values should be passed as values to CREATE/UPDATE SQL queries or not. * @param {boolean} [options.native=false] A flag that defines if native library shall be used or not. Currently only has an effect for postgres + * @param {boolean} [options.ssl=undefined] A flag that defines if connection should be over ssl or not * @param {boolean} [options.replication=false] Use read / write replication. To enable replication, pass an object, with two properties, read and write. Write should be an object (a single server for handling writes), and read an array of object (several servers to handle reads). Each read/write server can have the following properties: `host`, `port`, `username`, `password`, `database` * @param {object} [options.pool] sequelize connection pool configuration * @param {number} [options.pool.max=5] Maximum number of connection in pool @@ -286,6 +292,7 @@ class Sequelize { benchmark: false, minifyAliases: false, logQueryParameters: false, + attributeBehavior: 'throw', ...options }; @@ -339,6 +346,9 @@ class Sequelize { case 'mysql': Dialect = require('./dialects/mysql'); break; + case 'oracle': + Dialect = require('./dialects/oracle'); + break; case 'postgres': Dialect = require('./dialects/postgres'); break; @@ -352,7 +362,7 @@ class Sequelize { Dialect = require('./dialects/snowflake'); break; default: - throw new Error(`The dialect ${this.getDialect()} is not supported. Supported dialects: mssql, mariadb, mysql, postgres, db2 and sqlite.`); + throw new Error(`The dialect ${this.getDialect()} is not supported. Supported dialects: mssql, mariadb, mysql, oracle, postgres, db2 and sqlite.`); } this.dialect = new Dialect(this); @@ -641,7 +651,7 @@ class Sequelize { } finally { await this.runHooks('afterQuery', options, query); if (!options.transaction) { - await this.connectionManager.releaseConnection(connection); + this.connectionManager.releaseConnection(connection); } } }, retryOptions); @@ -792,33 +802,66 @@ class Sequelize { if (options.hooks) { await this.runHooks('beforeBulkSync', options); } + if (options.force) { await this.drop(options); } - const models = []; - - // Topologically sort by foreign key constraints to give us an appropriate - // creation order - this.modelManager.forEachModel(model => { - if (model) { - models.push(model); - } else { - // DB should throw an SQL error if referencing non-existent table - } - }); // no models defined, just authenticate - if (!models.length) { + if (this.modelManager.models.length === 0) { await this.authenticate(options); } else { - for (const model of models) await model.sync(options); + const models = this.modelManager.getModelsTopoSortedByForeignKey(); + if (models == null) { + return this._syncModelsWithCyclicReferences(options); + } + + // reverse to start with the one model that does not depend on anything + models.reverse(); + + // Topologically sort by foreign key constraints to give us an appropriate + // creation order + for (const model of models) { + await model.sync(options); + } } + if (options.hooks) { await this.runHooks('afterBulkSync', options); } + return this; } + /** + * Used instead of sync() when two models reference each-other, so their foreign keys cannot be created immediately. + * + * @param {object} options - sync options + * @private + */ + async _syncModelsWithCyclicReferences(options) { + if (this.dialect.name === 'sqlite') { + // Optimisation: no need to do this in two passes in SQLite because we can temporarily disable foreign keys + await withSqliteForeignKeysOff(this, options, async () => { + for (const model of this.modelManager.models) { + await model.sync(options); + } + }); + + return; + } + + // create all tables, but don't create foreign key constraints + for (const model of this.modelManager.models) { + await model.sync({ ...options, withoutForeignKeyConstraints: true }); + } + + // add foreign key constraints + for (const model of this.modelManager.models) { + await model.sync({ ...options, force: false, alter: true }); + } + } + /** * Truncate all tables defined through the sequelize models. * This is done by calling `Model.truncate()` on each model. @@ -831,13 +874,23 @@ class Sequelize { * {@link Model.truncate} for more information */ async truncate(options) { - const models = []; + const sortedModels = this.modelManager.getModelsTopoSortedByForeignKey(); + const models = sortedModels || this.modelManager.models; + const hasCyclicDependencies = sortedModels == null; - this.modelManager.forEachModel(model => { - if (model) { - models.push(model); - } - }, { reverse: false }); + // we have cyclic dependencies, cascade must be enabled. + if (hasCyclicDependencies && (!options || !options.cascade)) { + throw new Error('Sequelize#truncate: Some of your models have cyclic references (foreign keys). You need to use the "cascade" option to be able to delete rows from models that have cyclic references.'); + } + + // TODO [>=7]: throw if options.cascade is specified but unsupported in the given dialect. + if (hasCyclicDependencies && this.dialect.name === 'sqlite') { + // Workaround: SQLite does not support options.cascade, but we can disable its foreign key constraints while we + // truncate all tables. + return withSqliteForeignKeysOff(this, options, async () => { + await Promise.all(models.map(model => model.truncate(options))); + }); + } if (options && options.cascade) { for (const model of models) await model.truncate(options); @@ -859,15 +912,46 @@ class Sequelize { * @returns {Promise} */ async drop(options) { - const models = []; + // if 'cascade' is specified, we don't have to worry about cyclic dependencies. + if (options && options.cascade) { + for (const model of this.modelManager.models) { + await model.drop(options); + } + } - this.modelManager.forEachModel(model => { - if (model) { - models.push(model); + const sortedModels = this.modelManager.getModelsTopoSortedByForeignKey(); + + // no cyclic dependency between models, we can delete them in an order that will not cause an error. + if (sortedModels) { + for (const model of sortedModels) { + await model.drop(options); } - }, { reverse: false }); + } - for (const model of models) await model.drop(options); + if (this.dialect.name === 'sqlite') { + // Optimisation: no need to do this in two passes in SQLite because we can temporarily disable foreign keys + await withSqliteForeignKeysOff(this, options, async () => { + for (const model of this.modelManager.models) { + await model.drop(options); + } + }); + + return; + } + + // has cyclic dependency: we first remove each foreign key, then delete each model. + for (const model of this.modelManager.models) { + const tableName = model.getTableName(); + const foreignKeys = await this.queryInterface.getForeignKeyReferencesForTable(tableName, options); + + await Promise.all(foreignKeys.map(foreignKey => { + return this.queryInterface.removeConstraint(tableName, foreignKey.constraintName, options); + })); + } + + for (const model of this.modelManager.models) { + await model.drop(options); + } } /** @@ -885,7 +969,7 @@ class Sequelize { ...options }; - await this.query('SELECT 1+1 AS result', options); + await this.query(this.dialect.queryGenerator.authTestQuery(), options); return; } @@ -1085,6 +1169,7 @@ class Sequelize { * @param {string} [options.type='DEFERRED'] See `Sequelize.Transaction.TYPES` for possible options. Sqlite only. * @param {string} [options.isolationLevel] See `Sequelize.Transaction.ISOLATION_LEVELS` for possible options * @param {string} [options.deferrable] Sets the constraints to be deferred or immediately checked. See `Sequelize.Deferrable`. PostgreSQL Only + * @param {boolean} [options.readOnly] Whether this transaction will only be used to read data. Used to determine whether sequelize is allowed to use a read replication server. * @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql. * @param {Function} [autoCallback] The callback is called with the transaction object, and should return a promise. If the promise is resolved, the transaction commits; if the promise rejects, the transaction rolls back * @@ -1099,30 +1184,29 @@ class Sequelize { const transaction = new Transaction(this, options); if (!autoCallback) { - await transaction.prepareEnvironment(false); + await transaction.prepareEnvironment(/* cls */ false); return transaction; } // autoCallback provided return Sequelize._clsRun(async () => { + await transaction.prepareEnvironment(/* cls */ true); + + let result; try { - await transaction.prepareEnvironment(); - const result = await autoCallback(transaction); - await transaction.commit(); - return await result; + result = await autoCallback(transaction); } catch (err) { try { - if (!transaction.finished) { - await transaction.rollback(); - } else { - // release the connection, even if we don't need to rollback - await transaction.cleanup(); - } - } catch (err0) { - // ignore + await transaction.rollback(); + } catch (ignore) { + // ignore, because 'rollback' will already print the error before killing the connection } + throw err; } + + await transaction.commit(); + return result; }); } diff --git a/src/sql-string.js b/src/sql-string.js index d56c0468b300..1ce2828483ba 100644 --- a/src/sql-string.js +++ b/src/sql-string.js @@ -1,5 +1,6 @@ 'use strict'; +const moment = require('moment'); const dataTypes = require('./data-types'); const { logger } = require('./utils/logger'); @@ -28,11 +29,12 @@ function escape(val, timeZone, dialect, format) { // SQLite doesn't have true/false support. MySQL aliases true/false to 1/0 // for us. Postgres actually has a boolean type with true/false literals, // but sequelize doesn't use it yet. - if (['sqlite', 'mssql'].includes(dialect)) { + if (['sqlite', 'mssql', 'oracle'].includes(dialect)) { return +!!val; } return (!!val).toString(); case 'number': + case 'bigint': return val.toString(); case 'string': // In mssql, prepend N to all quoted vals which are originally a string (for @@ -74,6 +76,71 @@ function escape(val, timeZone, dialect, format) { // null character is not allowed in Postgres val = val.replace(/\0/g, '\\0'); } + } else if (dialect === 'oracle' && typeof val === 'string') { + if (val.startsWith('TO_TIMESTAMP_TZ') || val.startsWith('TO_DATE')) { + // Split the string using parentheses to isolate the function name, parameters, and potential extra parts + const splitVal = val.split(/\(|\)/); + + // Validate that the split result has exactly three parts (function name, parameters, and an empty string) + // and that there are no additional SQL commands after the function call (indicated by the last empty string). + if (splitVal.length !== 3 || splitVal[2] !== '') { + throw new Error('Invalid SQL function call.'); // Error if function call has unexpected format + } + + // Extract the function name (either 'TO_TIMESTAMP_TZ' or 'TO_DATE') and the contents inside the parentheses + const functionName = splitVal[0].trim(); // Function name should be 'TO_TIMESTAMP_TZ' or 'TO_DATE' + const insideParens = splitVal[1].trim(); // This contains the parameters (date value and format string) + + if (functionName !== 'TO_TIMESTAMP_TZ' && functionName !== 'TO_DATE') { + throw new Error('Invalid SQL function call. Expected TO_TIMESTAMP_TZ or TO_DATE.'); + } + + // Split the parameters inside the parentheses by commas (should contain exactly two: date and format) + const params = insideParens.split(','); + + // Validate that the parameters contain exactly two parts (date value and format string) + if (params.length !== 2) { + throw new Error('Unexpected input received.\nSequelize supports TO_TIMESTAMP_TZ or TO_DATE exclusively with a combination of value and format.'); + } + + // Extract the date value (first parameter) and remove single quotes around it + const dateValue = params[0].trim().replace(/'/g, ''); + const formatValue = params[1].trim(); + + if (functionName === 'TO_TIMESTAMP_TZ') { + const expectedFormat = "'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM'"; + // Validate that the formatValue is equal to expectedFormat since that is the only format used within sequelize + if (formatValue !== expectedFormat) { + throw new Error(`Invalid format string for TO_TIMESTAMP_TZ. Expected format: ${expectedFormat}`); + } + + // Validate the date value using Moment.js with the expected format + const formattedDate = moment(dateValue).format('YYYY-MM-DD HH:mm:ss.SSS Z'); + + // If the formatted date doesn't match the input date value, throw an error + if (formattedDate !== dateValue) { + throw new Error("Invalid date value for TO_TIMESTAMP_TZ. Expected format: 'YYYY-MM-DD HH:mm:ss.SSS Z'"); + } + } else if (functionName === 'TO_DATE') { + const expectedFormat = "'YYYY/MM/DD'"; + // Validate that the formatValue is equal to expectedFormat since that is the only format used within sequelize + if (formatValue !== expectedFormat) { + throw new Error(`Invalid format string for TO_DATE. Expected format: ${expectedFormat}`); + } + + // Validate the date value using Moment.js with the expected format + const formattedDate = moment(dateValue).format('YYYY-MM-DD'); + + // If the formatted date doesn't match the input date value, throw an error + if (formattedDate !== dateValue) { + throw new Error("Invalid date value for TO_DATE. Expected format: 'YYYY-MM-DD'"); + } + } + + return val; + } + + val = val.replace(/'/g, "''"); } else { // eslint-disable-next-line no-control-regex diff --git a/src/transaction.d.ts b/src/transaction.d.ts index 0ebc2cad0933..64255fab15bb 100644 --- a/src/transaction.d.ts +++ b/src/transaction.d.ts @@ -29,14 +29,14 @@ export class Transaction { /** * Returns possible options for row locking */ - static get LOCK(): LOCK; + static get LOCK(): typeof LOCK; /** * Same as its static version, but can also be called on instances of * transactions to get possible options for row locking directly from the * instance. */ - get LOCK(): LOCK; + get LOCK(): typeof LOCK; } // tslint:disable-next-line no-namespace @@ -131,13 +131,6 @@ export enum LOCK { NO_KEY_UPDATE = 'NO KEY UPDATE', } -interface LOCK { - UPDATE: LOCK.UPDATE; - SHARE: LOCK.SHARE; - KEY_SHARE: LOCK.KEY_SHARE; - NO_KEY_UPDATE: LOCK.NO_KEY_UPDATE; -} - /** * Options provided when the transaction is created */ @@ -146,6 +139,7 @@ export interface TransactionOptions extends Logging { isolationLevel?: Transaction.ISOLATION_LEVELS; type?: Transaction.TYPES; deferrable?: string | Deferrable; + readOnly?: boolean; /** * Parent transaction. */ diff --git a/src/transaction.js b/src/transaction.js index f8e32f18df92..f4a97ce7f3f7 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -17,6 +17,7 @@ class Transaction { * @param {string} [options.type] Sets the type of the transaction. Sqlite only * @param {string} [options.isolationLevel] Sets the isolation level of the transaction. * @param {string} [options.deferrable] Sets the constraints to be deferred or immediately checked. PostgreSQL only + * @param {boolean} [options.readOnly] Whether this transaction will only be used to read data. Used to determine whether sequelize is allowed to use a read replication server. */ constructor(sequelize, options) { this.sequelize = sequelize; @@ -57,10 +58,15 @@ class Transaction { } try { - return await this.sequelize.getQueryInterface().commitTransaction(this, this.options); + await this.sequelize.getQueryInterface().commitTransaction(this, this.options); + this.cleanup(); + } catch (e) { + console.warn(`Committing transaction ${this.id} failed with error ${JSON.stringify(e.message)}. We are killing its connection as it is now in an undetermined state.`); + await this.forceCleanup(); + + throw e; } finally { this.finished = 'commit'; - this.cleanup(); for (const hook of this._afterCommitHooks) { await hook.apply(this, [this]); } @@ -82,12 +88,17 @@ class Transaction { } try { - return await this + await this .sequelize .getQueryInterface() .rollbackTransaction(this, this.options); - } finally { + this.cleanup(); + } catch (e) { + console.warn(`Rolling back transaction ${this.id} failed with error ${JSON.stringify(e.message)}. We are killing its connection as it is now in an undetermined state.`); + await this.forceCleanup(); + + throw e; } } @@ -98,13 +109,9 @@ class Transaction { * @param {boolean} useCLS Defaults to true: Use CLS (Continuation Local Storage) with Sequelize. With CLS, all queries within the transaction callback will automatically receive the transaction object. * @returns {Promise} */ - async prepareEnvironment(useCLS) { + async prepareEnvironment(useCLS = true) { let connectionPromise; - if (useCLS === undefined) { - useCLS = true; - } - if (this.parent) { connectionPromise = Promise.resolve(this.parent.connection); } else { @@ -131,6 +138,7 @@ class Transaction { } } + // TODO (@ephys) [>=7.0.0]: move this inside of sequelize.transaction, remove parameter. if (useCLS && this.sequelize.constructor._cls) { this.sequelize.constructor._cls.set('transaction', this); } @@ -163,12 +171,31 @@ class Transaction { cleanup() { // Don't release the connection if there's a parent transaction or // if we've already cleaned up - if (this.parent || this.connection.uuid === undefined) return; + if (this.parent || this.connection.uuid === undefined) { + return; + } + + this._clearCls(); + this.sequelize.connectionManager.releaseConnection(this.connection); + this.connection.uuid = undefined; + } + + /** + * Kills the connection this transaction uses. + * Used as a last resort, for instance because COMMIT or ROLLBACK resulted in an error + * and the transaction is left in a broken state, + * and releasing the connection to the pool would be dangerous. + */ + async forceCleanup() { + // Don't release the connection if there's a parent transaction or + // if we've already cleaned up + if (this.parent || this.connection.uuid === undefined) { + return; + } this._clearCls(); - const res = this.sequelize.connectionManager.releaseConnection(this.connection); + await this.sequelize.connectionManager.destroyConnection(this.connection); this.connection.uuid = undefined; - return res; } _clearCls() { diff --git a/src/utils.js b/src/utils.js index 3ac0bd421c5e..9bc431002c74 100644 --- a/src/utils.js +++ b/src/utils.js @@ -336,7 +336,7 @@ function removeNullValuesFromHash(hash, omitNull, options) { } exports.removeNullValuesFromHash = removeNullValuesFromHash; -const dialects = new Set(['mariadb', 'mysql', 'postgres', 'sqlite', 'mssql', 'db2']); +const dialects = new Set(['mariadb', 'mysql', 'postgres', 'sqlite', 'mssql', 'db2', 'oracle']); function now(dialect) { const d = new Date(); diff --git a/src/utils/deprecations.ts b/src/utils/deprecations.ts index c5ef8cb746e6..07c040dfe881 100644 --- a/src/utils/deprecations.ts +++ b/src/utils/deprecations.ts @@ -2,7 +2,6 @@ import { deprecate } from 'util'; const noop = () => { /* noop */ }; -export const noRawAttributes = deprecate(noop, 'Use sequelize.fn / sequelize.literal to construct attributes', 'SEQUELIZE0001'); export const noTrueLogging = deprecate(noop, 'The logging-option should be either a function or false. Default: console.log', 'SEQUELIZE0002'); export const noStringOperators = deprecate(noop, 'String based operators are deprecated. Please use Symbol based operators for better security, read more at https://sequelize.org/master/manual/querying.html#operators', 'SEQUELIZE0003'); export const noBoolOperatorAliases = deprecate(noop, 'A boolean value was passed to options.operatorsAliases. This is a no-op with v5 and should be removed.', 'SEQUELIZE0004'); diff --git a/src/utils/sql.ts b/src/utils/sql.ts index c252cd2704ea..1e0697ea2b04 100644 --- a/src/utils/sql.ts +++ b/src/utils/sql.ts @@ -38,6 +38,7 @@ export function injectReplacements( let previousSliceEnd = 0; let isSingleLineComment = false; let isCommentBlock = false; + let stringIsBackslashEscapable = false; for (let i = 0; i < sqlString.length; i++) { const char = sqlString[i]; @@ -51,8 +52,12 @@ export function injectReplacements( } if (isString) { - if (char === '\'' && !isBackslashEscaped(sqlString, i - 1)) { + if ( + char === '\'' && + (!stringIsBackslashEscapable || !isBackslashEscaped(sqlString, i - 1)) + ) { isString = false; + stringIsBackslashEscapable = false; } continue; @@ -65,8 +70,8 @@ export function injectReplacements( const remainingString = sqlString.slice(i, sqlString.length); - const dollarStringStartMatch = remainingString.match(/^\$(?[a-z_][0-9a-z_])?(\$)/i); - const tagName = dollarStringStartMatch?.groups?.name; + const dollarStringStartMatch = remainingString.match(/^\$(?[a-z_][0-9a-z_]*)?(\$)/i); + const tagName = dollarStringStartMatch?.groups?.name || ''; if (currentDollarStringTagName === tagName) { currentDollarStringTagName = null; } @@ -97,6 +102,23 @@ export function injectReplacements( if (char === '\'') { isString = true; + + // The following query is supported in almost all dialects, + // SELECT E'test'; + // but postgres interprets it as an E-prefixed string, while other dialects interpret it as + // SELECT E 'test'; + // which selects the type E and aliases it to 'test'. + + stringIsBackslashEscapable = + // all ''-style strings in this dialect can be backslash escaped + dialect.canBackslashEscape() || + // checking if this is a postgres-style E-prefixed string, which also supports backslash escaping + dialect.supports.escapeStringConstants && + // is this a E-prefixed string, such as `E'abc'`, `e'abc'` ? + (sqlString[i - 1] === 'E' || sqlString[i - 1] === 'e') && + // reject things such as `AE'abc'` (the prefix must be exactly E) + canPrecedeNewToken(sqlString[i - 2]); + continue; } @@ -121,9 +143,10 @@ export function injectReplacements( const remainingString = sqlString.slice(i, sqlString.length); - const dollarStringStartMatch = remainingString.match(/^\$(?[a-z_][0-9a-z_]*)?\$/i); + const dollarStringStartMatch = remainingString.match(/^\$(?[a-z_][0-9a-z_]*)?(\$)/i); if (dollarStringStartMatch) { currentDollarStringTagName = dollarStringStartMatch.groups?.name ?? ''; + i += dollarStringStartMatch[0].length - 1; continue; } @@ -134,14 +157,14 @@ export function injectReplacements( if (isNamedReplacements && char === ':') { const previousChar = sqlString[i - 1]; // we want to be conservative with what we consider to be a replacement to avoid risk of conflict with potential operators - // users need to add a space before the bind parameter (except after '(', ',', and '=') - if (previousChar !== undefined && !/[\s(,=]/.test(previousChar)) { + // users need to add a space before the bind parameter (except after '(', ',', and '=', '[' (for arrays)) + if (!canPrecedeNewToken(previousChar) && previousChar !== '[') { continue; } const remainingString = sqlString.slice(i, sqlString.length); - const match = remainingString.match(/^:(?[a-z_][0-9a-z_]*)(?:\)|,|$|\s|::)/i); + const match = remainingString.match(/^:(?[a-z_][0-9a-z_]*)(?:\)|,|$|\s|::|;|])/i); const replacementName = match?.groups?.name; if (!replacementName) { continue; @@ -169,8 +192,10 @@ export function injectReplacements( const previousChar = sqlString[i - 1]; // we want to be conservative with what we consider to be a replacement to avoid risk of conflict with potential operators - // users need to add a space before the bind parameter (except after '(', ',', and '=') - if (previousChar !== undefined && !/[\s(,=]/.test(previousChar)) { + // users need to add a space before the bind parameter (except after '(', ',', and '=', '[' (for arrays)) + // -> [ is temporarily added to allow 'ARRAY[:name]' to be replaced + // https://github.com/sequelize/sequelize/issues/14410 will make this obsolete. + if (!canPrecedeNewToken(previousChar) && previousChar !== '[') { continue; } @@ -201,11 +226,21 @@ export function injectReplacements( } } + if (isString) { + throw new Error( + `The following SQL query includes an unterminated string literal:\n${sqlString}` + ); + } + output += sqlString.slice(previousSliceEnd, sqlString.length); return output; } +function canPrecedeNewToken(char: string | undefined): boolean { + return char === undefined || /[\s(>,=]/.test(char); +} + function isBackslashEscaped(string: string, pos: number): boolean { let escaped = false; for (let i = pos; i >= 0; i--) { diff --git a/test/config/config.js b/test/config/config.js index f914d04e8efd..20796e26c9be 100644 --- a/test/config/config.js +++ b/test/config/config.js @@ -81,5 +81,17 @@ module.exports = { max: process.env.SEQ_DB2_POOL_MAX || process.env.SEQ_POOL_MAX || 5, idle: process.env.SEQ_DB2_POOL_IDLE || process.env.SEQ_POOL_IDLE || 3000 } + }, + + oracle: { + database: env.SEQ_ORACLE_DB || env.SEQ_DB || 'XEPDB1', + username: env.SEQ_ORACLE_USER || env.SEQ_USER || 'sequelizetest', + password: env.SEQ_ORACLE_PW || env.SEQ_PW || 'sequelizepassword', + host: env.SEQ_ORACLE_HOST || env.SEQ_HOST || '127.0.0.1', + port: env.SEQ_ORACLE_PORT || env.SEQ_PORT || 1521, + pool: { + max: env.SEQ_ORACLE_POOL_MAX || env.SEQ_POOL_MAX || 5, + idle: env.SEQ_ORACLE_POOL_IDLE || env.SEQ_POOL_IDLE || 3000 + } } }; diff --git a/test/integration/associations/belongs-to-many.test.js b/test/integration/associations/belongs-to-many.test.js index 0425e06c2397..c88c2962efe9 100644 --- a/test/integration/associations/belongs-to-many.test.js +++ b/test/integration/associations/belongs-to-many.test.js @@ -1417,7 +1417,12 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), () => { describe('hasAssociations with binary key', () => { beforeEach(function() { - const keyDataType = ['mysql', 'mariadb', 'db2'].includes(dialect) ? 'BINARY(255)' : DataTypes.BLOB('tiny'); + let keyDataType = DataTypes.BLOB('tiny'); + if (['mysql', 'mariadb', 'db2'].includes(dialect)) { + keyDataType = 'BINARY(255)'; + } else if (dialect === 'oracle') { + keyDataType = DataTypes.STRING(255, true); + } this.Article = this.sequelize.define('Article', { id: { type: keyDataType, @@ -3115,7 +3120,7 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), () => { await this.sequelize.sync({ force: true }); let result = await this.sequelize.getQueryInterface().showAllTables(); - if (['mssql', 'mariadb', 'db2'].includes(dialect)) { + if (['mssql', 'mariadb', 'db2', 'oracle'].includes(dialect)) { result = result.map(v => v.tableName); } @@ -3132,7 +3137,7 @@ describe(Support.getTestDialectTeaser('BelongsToMany'), () => { await this.sequelize.sync({ force: true }); let result = await this.sequelize.getQueryInterface().showAllTables(); - if (['mssql', 'mariadb', 'db2'].includes(dialect)) { + if (['mssql', 'mariadb', 'db2', 'oracle'].includes(dialect)) { result = result.map(v => v.tableName); } diff --git a/test/integration/associations/belongs-to.test.js b/test/integration/associations/belongs-to.test.js index 6c4506f3e06e..011d7ac18cfb 100644 --- a/test/integration/associations/belongs-to.test.js +++ b/test/integration/associations/belongs-to.test.js @@ -625,8 +625,7 @@ describe(Support.getTestDialectTeaser('BelongsTo'), () => { } // NOTE: mssql does not support changing an autoincrement primary key - if (Support.getTestDialect() !== 'mssql' && - Support.getTestDialect() !== 'db2') { + if (!['mssql', 'db2', 'oracle'].includes(Support.getTestDialect())) { it('can cascade updates', async function() { const Task = this.sequelize.define('Task', { title: DataTypes.STRING }), User = this.sequelize.define('User', { username: DataTypes.STRING }); diff --git a/test/integration/associations/has-many.test.js b/test/integration/associations/has-many.test.js index 340fa3494bc9..114ebe596708 100644 --- a/test/integration/associations/has-many.test.js +++ b/test/integration/associations/has-many.test.js @@ -1102,7 +1102,7 @@ describe(Support.getTestDialectTeaser('HasMany'), () => { }); // NOTE: mssql does not support changing an autoincrement primary key - if (dialect !== 'mssql' && dialect !== 'db2') { + if (!['mssql', 'db2', 'oracle'].includes(dialect)) { it('can cascade updates', async function() { const Task = this.sequelize.define('Task', { title: DataTypes.STRING }), User = this.sequelize.define('User', { username: DataTypes.STRING }); diff --git a/test/integration/associations/has-one.test.js b/test/integration/associations/has-one.test.js index e68cf25539a6..3f4a430fe574 100644 --- a/test/integration/associations/has-one.test.js +++ b/test/integration/associations/has-one.test.js @@ -453,8 +453,7 @@ describe(Support.getTestDialectTeaser('HasOne'), () => { }); // NOTE: mssql does not support changing an autoincrement primary key - if (Support.getTestDialect() !== 'mssql' && - Support.getTestDialect() !== 'db2') { + if (!['mssql', 'db2', 'oracle'].includes(Support.getTestDialect())) { it('can cascade updates', async function() { const Task = this.sequelize.define('Task', { title: Sequelize.STRING }), User = this.sequelize.define('User', { username: Sequelize.STRING }); diff --git a/test/integration/cls.test.js b/test/integration/cls.test.js index 746d43996842..1a2f2b7bce56 100644 --- a/test/integration/cls.test.js +++ b/test/integration/cls.test.js @@ -136,13 +136,261 @@ if (current.dialect.supports.transactions) { }); }); + describe('Model Hook integration', () => { + + function testHooks({ method, hooks: hookNames, optionPos, execute, getModel }) { + it(`passes the transaction to hooks {${hookNames.join(',')}} when calling ${method}`, async function() { + await this.sequelize.transaction(async transaction => { + const hooks = Object.create(null); + + for (const hookName of hookNames) { + hooks[hookName] = sinon.spy(); + } + + const User = Reflect.apply(getModel, this, []); + + for (const [hookName, spy] of Object.entries(hooks)) { + User[hookName](spy); + } + + await Reflect.apply(execute, this, [User]); + + const spyMatcher = []; + // ignore all arguments until we get to the option bag. + for (let i = 0; i < optionPos; i++) { + spyMatcher.push(sinon.match.any); + } + + // find the transaction in the option bag + spyMatcher.push(sinon.match.has('transaction', transaction)); + + for (const [hookName, spy] of Object.entries(hooks)) { + expect( + spy, + `hook ${hookName} did not receive the transaction from CLS.` + ).to.have.been.calledWith(...spyMatcher); + } + }); + }); + } + + testHooks({ + method: 'Model.bulkCreate', + hooks: ['beforeBulkCreate', 'beforeCreate', 'afterCreate', 'afterBulkCreate'], + optionPos: 1, + async execute(User) { + await User.bulkCreate([{ name: 'bob' }], { individualHooks: true }); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model.findAll', + hooks: ['beforeFind', 'beforeFindAfterExpandIncludeAll', 'beforeFindAfterOptions'], + optionPos: 0, + async execute(User) { + await User.findAll(); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model.findAll', + hooks: ['afterFind'], + optionPos: 1, + async execute(User) { + await User.findAll(); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model.count', + hooks: ['beforeCount'], + optionPos: 0, + async execute(User) { + await User.count(); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model.upsert', + hooks: ['beforeUpsert', 'afterUpsert'], + optionPos: 1, + async execute(User) { + await User.upsert({ + id: 1, + name: 'bob' + }); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model.destroy', + hooks: ['beforeBulkDestroy', 'afterBulkDestroy'], + optionPos: 0, + async execute(User) { + await User.destroy({ where: { name: 'bob' } }); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model.destroy with individualHooks', + hooks: ['beforeDestroy', 'beforeDestroy'], + optionPos: 1, + async execute(User) { + await User.create({ name: 'bob' }); + await User.destroy({ where: { name: 'bob' }, individualHooks: true }); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model#destroy', + hooks: ['beforeDestroy', 'beforeDestroy'], + optionPos: 1, + async execute(User) { + const user = await User.create({ name: 'bob' }); + await user.destroy(); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model.update', + hooks: ['beforeBulkUpdate', 'afterBulkUpdate'], + optionPos: 0, + async execute(User) { + await User.update({ name: 'alice' }, { where: { name: 'bob' } }); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model.update with individualHooks', + hooks: ['beforeUpdate', 'afterUpdate'], + optionPos: 1, + async execute(User) { + await User.create({ name: 'bob' }); + await User.update({ name: 'alice' }, { where: { name: 'bob' }, individualHooks: true }); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model#save (isNewRecord)', + hooks: ['beforeCreate', 'afterCreate'], + optionPos: 1, + async execute(User) { + const user = User.build({ name: 'bob' }); + user.name = 'alice'; + await user.save(); + }, + getModel() { + return this.User; + } + }); + + testHooks({ + method: 'Model#save (!isNewRecord)', + hooks: ['beforeUpdate', 'afterUpdate'], + optionPos: 1, + async execute(User) { + const user = await User.create({ name: 'bob' }); + user.name = 'alice'; + await user.save(); + }, + getModel() { + return this.User; + } + }); + + describe('paranoid restore', () => { + beforeEach(async function() { + this.ParanoidUser = this.sequelize.define('ParanoidUser', { + name: Sequelize.STRING + }, { paranoid: true }); + + await this.ParanoidUser.sync({ force: true }); + }); + + testHooks({ + method: 'Model.restore', + hooks: ['beforeBulkRestore', 'afterBulkRestore'], + optionPos: 0, + async execute() { + const User = this.ParanoidUser; + await User.restore({ where: { name: 'bob' } }); + }, + getModel() { + return this.ParanoidUser; + } + }); + + testHooks({ + method: 'Model.restore with individualHooks', + hooks: ['beforeRestore', 'afterRestore'], + optionPos: 1, + async execute() { + const User = this.ParanoidUser; + + await User.create({ name: 'bob' }); + await User.destroy({ where: { name: 'bob' } }); + await User.restore({ where: { name: 'bob' }, individualHooks: true }); + }, + getModel() { + return this.ParanoidUser; + } + }); + + testHooks({ + method: 'Model#restore', + hooks: ['beforeRestore', 'afterRestore'], + optionPos: 1, + async execute() { + const User = this.ParanoidUser; + + const user = await User.create({ name: 'bob' }); + await user.destroy(); + await user.restore(); + }, + getModel() { + return this.ParanoidUser; + } + }); + }); + }); + it('CLS namespace is stored in Sequelize._cls', function() { expect(Sequelize._cls).to.equal(this.ns); }); it('promises returned by sequelize.query are correctly patched', async function() { await this.sequelize.transaction(async t => { - await this.sequelize.query('select 1', { type: Sequelize.QueryTypes.SELECT }); + await this.sequelize.query(`select 1${ Support.addDualInSelect()}`, { type: Sequelize.QueryTypes.SELECT }); return expect(this.ns.get('transaction')).to.equal(t); } ); @@ -160,12 +408,12 @@ if (current.dialect.supports.transactions) { const result = this.ns.runPromise(async () => { this.ns.set('value', 1); await delay(500); - return sequelize.query('select 1;'); + return sequelize.query(`select 1${ Support.addDualInSelect() };`); }); await this.ns.runPromise(() => { this.ns.set('value', 2); - return sequelize.query('select 2;'); + return sequelize.query(`select 2${ Support.addDualInSelect() };`); }); await result; diff --git a/test/integration/configuration.test.js b/test/integration/configuration.test.js index 4a7fa5cd11d5..888066e86605 100644 --- a/test/integration/configuration.test.js +++ b/test/integration/configuration.test.js @@ -60,13 +60,11 @@ describe(Support.getTestDialectTeaser('Configuration'), () => { if (dialect === 'sqlite') { // SQLite doesn't require authentication and `select 1 as hello` is a valid query, so this should be fulfilled not rejected for it. await expect(seq.query('select 1 as hello')).to.eventually.be.fulfilled; - } - - else if (dialect === 'db2') { + } else if (dialect === 'db2') { await expect(seq.query('select 1 as hello')).to.eventually.be.rejectedWith(...willBeRejectedWithArgs); - } - - else { + } else if (dialect === 'oracle') { + await expect(seq.query('select 1 as hello FROM DUAL')).to.eventually.be.rejectedWith(Sequelize.HostNotReachableError); + } else { await expect(seq.query('select 1 as hello')).to.eventually.be.rejectedWith(Sequelize.ConnectionRefusedError, 'connect ECONNREFUSED'); } }); @@ -74,7 +72,7 @@ describe(Support.getTestDialectTeaser('Configuration'), () => { it('when we don\'t have a valid dialect.', () => { expect(() => { new Sequelize(config[dialect].database, config[dialect].username, config[dialect].password, { host: '0.0.0.1', port: config[dialect].port, dialect: 'some-fancy-dialect' }); - }).to.throw(Error, 'The dialect some-fancy-dialect is not supported. Supported dialects: mssql, mariadb, mysql, postgres, db2 and sqlite.'); + }).to.throw(Error, 'The dialect some-fancy-dialect is not supported. Supported dialects: mssql, mariadb, mysql, oracle, postgres, db2 and sqlite.'); }); }); diff --git a/test/integration/data-types.test.js b/test/integration/data-types.test.js index 6899d26e2b59..c20666a0b844 100644 --- a/test/integration/data-types.test.js +++ b/test/integration/data-types.test.js @@ -33,6 +33,22 @@ describe(Support.getTestDialectTeaser('DataTypes'), () => { return value.format('YYYY-MM-DD HH:mm:ss'); }); + // oracle has a _bindParam function that checks if DATE was created with + // the boolean param (if so it outputs a Buffer bind param). This override + // isn't needed for other dialects + let bindParam; + if (dialect === 'oracle') { + bindParam = Sequelize.DATE.prototype.bindParam = sinon.spy(function(value, options) { + if (!moment.isMoment(value)) { + value = this._applyTimezone(value, options); + } + // For the Oracle dialect, use TO_DATE() + const formatedDate = value.format('YYYY-MM-DD HH:mm:ss'); + const format = 'YYYY-MM-DD HH24:mi:ss'; + return `TO_DATE('${formatedDate}', '${format}')`; + }); + } + current.refreshTypes(); const User = current.define('user', { @@ -50,7 +66,9 @@ describe(Support.getTestDialectTeaser('DataTypes'), () => { const obj = await User.findAll(); const user = obj[0]; expect(parse).to.have.been.called; - expect(stringify).to.have.been.called; + // For the Oracle dialect we check if bindParam was called + // for other dalects we check if stringify was called + dialect === 'oracle' ? expect(bindParam).to.have.been.called : expect(stringify).to.have.been.called; expect(moment.isMoment(user.dateField)).to.be.ok; @@ -115,7 +133,14 @@ describe(Support.getTestDialectTeaser('DataTypes'), () => { it('calls parse and stringify for JSON', async () => { const Type = new Sequelize.JSON(); - await testSuccess(Type, { test: 42, nested: { foo: 'bar' } }); + // oracle has a _bindParam function that checks if JSON was created with + // the boolean param (if so it outputs a Buffer bind param). This override + // isn't needed for other dialects + if (dialect === 'oracle') { + await testSuccess(Type, { test: 42, nested: { foo: 'bar' } }, { useBindParam: true }); + } else { + await testSuccess(Type, { test: 42, nested: { foo: 'bar' } }); + } }); } @@ -146,19 +171,38 @@ describe(Support.getTestDialectTeaser('DataTypes'), () => { it('calls parse and stringify for DATE', async () => { const Type = new Sequelize.DATE(); - await testSuccess(Type, new Date()); + // oracle has a _bindParam function that checks if DATE was created with + // the boolean param (if so it outputs a Buffer bind param). This override + // isn't needed for other dialects + if (dialect === 'oracle') { + await testSuccess(Type, new Date(), { useBindParam: true }); + } else { + await testSuccess(Type, new Date()); + } }); it('calls parse and stringify for DATEONLY', async () => { const Type = new Sequelize.DATEONLY(); - await testSuccess(Type, moment(new Date()).format('YYYY-MM-DD')); + // oracle has a _bindParam function that checks if DATEONLY was created with + // the boolean param (if so it outputs a Buffer bind param). This override + // isn't needed for other dialects + if (dialect === 'oracle') { + await testSuccess(Type, moment(new Date()).format('YYYY-MM-DD'), { useBindParam: true }); + } else { + await testSuccess(Type, moment(new Date()).format('YYYY-MM-DD')); + } }); it('calls parse and stringify for TIME', async () => { const Type = new Sequelize.TIME(); - await testSuccess(Type, moment(new Date()).format('HH:mm:ss')); + // TIME Datatype isn't supported by the oracle dialect + if (dialect === 'oracle') { + testFailure(Type); + } else { + await testSuccess(Type, moment(new Date()).format('HH:mm:ss')); + } }); it('calls parse and stringify for BLOB', async () => { @@ -170,16 +214,23 @@ describe(Support.getTestDialectTeaser('DataTypes'), () => { it('calls parse and stringify for CHAR', async () => { const Type = new Sequelize.CHAR(); - await testSuccess(Type, 'foobar'); + // oracle has a _bindParam function that checks if STRING was created with + // the boolean param (if so it outputs a Buffer bind param). This override + // isn't needed for other dialects + if (dialect === 'oracle') { + await testSuccess(Type, 'foobar', { useBindParam: true }); + } else { + await testSuccess(Type, 'foobar'); + } }); it('calls parse and stringify/bindParam for STRING', async () => { const Type = new Sequelize.STRING(); - // mssql has a _bindParam function that checks if STRING was created with + // mssql/oracle has a _bindParam function that checks if STRING was created with // the boolean param (if so it outputs a Buffer bind param). This override // isn't needed for other dialects - if (dialect === 'mssql' || dialect === 'db2') { + if (['mssql', 'db2', 'oracle'].includes(dialect)) { await testSuccess(Type, 'foobar', { useBindParam: true }); } else { await testSuccess(Type, 'foobar'); @@ -237,12 +288,19 @@ describe(Support.getTestDialectTeaser('DataTypes'), () => { const user = await User.create({ age }); expect(BigInt(user.age).toString()).to.equal(age.toString()); + // cover also bulkCreate + // adds two records + await User.bulkCreate([{ age }, { age }]); + const users = await User.findAll({ where: { age } }); - expect(users).to.have.lengthOf(1); - expect(BigInt(users[0].age).toString()).to.equal(age.toString()); + expect(users).to.have.lengthOf(3); + for (const usr of users) { + expect(BigInt(usr.age).toString()).to.equal(age.toString()); + } + }); if (dialect === 'mysql') { @@ -308,7 +366,7 @@ describe(Support.getTestDialectTeaser('DataTypes'), () => { const Type = new Sequelize.UUID(); // there is no dialect.supports.UUID yet - if (['postgres', 'sqlite', 'db2'].includes(dialect)) { + if (['postgres', 'sqlite', 'oracle', 'db2'].includes(dialect)) { await testSuccess(Type, uuid.v4()); } else { // No native uuid type @@ -377,7 +435,7 @@ describe(Support.getTestDialectTeaser('DataTypes'), () => { it('calls parse and stringify for ENUM', async () => { const Type = new Sequelize.ENUM('hat', 'cat'); - if (['postgres', 'db2'].includes(dialect)) { + if (['postgres', 'oracle', 'db2'].includes(dialect)) { await testSuccess(Type, 'hat'); } else { testFailure(Type); @@ -462,7 +520,7 @@ describe(Support.getTestDialectTeaser('DataTypes'), () => { }); } - if (['postgres', 'sqlite'].includes(dialect)) { + if (['postgres', 'sqlite', 'oracle'].includes(dialect)) { // postgres actively supports IEEE floating point literals, and sqlite doesn't care what we throw at it it('should store and parse IEEE floating point literals (NaN and Infinity)', async function() { const Model = this.sequelize.define('model', { diff --git a/test/integration/dialects/oracle/connection-manager.test.js b/test/integration/dialects/oracle/connection-manager.test.js new file mode 100644 index 000000000000..a63ec8e421f1 --- /dev/null +++ b/test/integration/dialects/oracle/connection-manager.test.js @@ -0,0 +1,18 @@ +'use strict'; + +const chai = require('chai'); +const expect = chai.expect; +const config = require('../../../config/config.js').oracle; +const Support = require('../../support'); +const dialect = Support.getTestDialect(); +const Sequelize = Support.Sequelize; + +if (dialect === 'oracle') { + describe('[Oracle Specific] Connection Manager', () => { + it('connect string authentication using connection Descriptor', async () => { + const connDesc = `(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=${config.host})(PORT=${config.port}))(CONNECT_DATA=(SERVICE_NAME=${config.database})))`; + const sequelize = new Sequelize({ username: config.username, password: config.password, dialect: 'oracle', dialectOptions: { connectString: connDesc } }); + await expect(sequelize.authenticate()).not.to.be.rejected; + }); + }); +} diff --git a/test/integration/dialects/postgres/query.test.js b/test/integration/dialects/postgres/query.test.js index 55085a6ccf6a..27d264e6a128 100644 --- a/test/integration/dialects/postgres/query.test.js +++ b/test/integration/dialects/postgres/query.test.js @@ -4,7 +4,8 @@ const chai = require('chai'), expect = chai.expect, Support = require('../../support'), dialect = Support.getTestDialect(), - DataTypes = require('sequelize/lib/data-types'); + DataTypes = require('sequelize/lib/data-types'), + DatabaseError = require('sequelize/lib/errors/database-error'); if (dialect.match(/^postgres/)) { describe('[POSTGRES] Query', () => { @@ -102,5 +103,135 @@ if (dialect.match(/^postgres/)) { } }); }); + + it('orders by a literal when subquery and minifyAliases are enabled', async () => { + const sequelizeMinifyAliases = Support.createSequelizeInstance({ + logQueryParameters: true, + benchmark: true, + minifyAliases: true, + define: { + timestamps: false + } + }); + + const Foo = sequelizeMinifyAliases.define('Foo', { + name: { + field: 'my_name', + type: DataTypes.TEXT + } + }, { timestamps: false }); + + await sequelizeMinifyAliases.sync({ force: true }); + await Foo.create({ name: 'record1' }); + await Foo.create({ name: 'record2' }); + + const baseTest = (await Foo.findAll({ + subQuery: false, + order: sequelizeMinifyAliases.literal('"Foo".my_name') + })).map(f => f.name); + expect(baseTest[0]).to.equal('record1'); + + const orderByAscSubquery = (await Foo.findAll({ + attributes: { + include: [ + [sequelizeMinifyAliases.literal('"Foo".my_name'), 'customAttribute'] + ] + }, + subQuery: true, + order: [['customAttribute']], + limit: 1 + })).map(f => f.name); + expect(orderByAscSubquery[0]).to.equal('record1'); + + const orderByDescSubquery = (await Foo.findAll({ + attributes: { + include: [ + [sequelizeMinifyAliases.literal('"Foo".my_name'), 'customAttribute'] + ] + }, + subQuery: true, + order: [['customAttribute', 'DESC']], + limit: 1 + })).map(f => f.name); + expect(orderByDescSubquery[0]).to.equal('record2'); + }); + + it('returns the minified aliased attributes', async () => { + const sequelizeMinifyAliases = Support.createSequelizeInstance({ + logQueryParameters: true, + benchmark: true, + minifyAliases: true, + define: { + timestamps: false + } + }); + + const Foo = sequelizeMinifyAliases.define( + 'Foo', + { + name: { + field: 'my_name', + type: DataTypes.TEXT + } + }, + { timestamps: false } + ); + + await sequelizeMinifyAliases.sync({ force: true }); + + await Foo.findAll({ + subQuery: false, + attributes: { + include: [ + [sequelizeMinifyAliases.literal('"Foo".my_name'), 'order_0'] + ] + }, + order: [['order_0', 'DESC']] + }); + }); + + describe('Connection Invalidation', () => { + if (process.env.DIALECT === 'postgres-native') { + // native driver doesn't support statement_timeout or query_timeout + return; + } + + async function setUp(clientQueryTimeoutMs) { + const sequelize = Support.createSequelizeInstance({ + dialectOptions: { + statement_timeout: 500, // ms + query_timeout: clientQueryTimeoutMs + }, + pool: { + max: 1, // having only one helps us know whether the connection was invalidated + idle: 60000 + } + }); + + return { sequelize, originalPid: await getConnectionPid(sequelize) }; + } + + async function getConnectionPid(sequelize) { + const connection = await sequelize.connectionManager.getConnection(); + const pid = connection.processID; + sequelize.connectionManager.releaseConnection(connection); + + return pid; + } + + it('reuses connection after statement timeout', async () => { + // client timeout > statement timeout means that the query should fail with a statement timeout + const { sequelize, originalPid } = await setUp(10000); + await expect(sequelize.query('select pg_sleep(1)')).to.eventually.be.rejectedWith(DatabaseError, 'canceling statement due to statement timeout'); + expect(await getConnectionPid(sequelize)).to.equal(originalPid); + }); + + it('invalidates connection after client-side query timeout', async () => { + // client timeout < statement timeout means that the query should fail with a read timeout + const { sequelize, originalPid } = await setUp(250); + await expect(sequelize.query('select pg_sleep(1)')).to.eventually.be.rejectedWith(DatabaseError, 'Query read timeout'); + expect(await getConnectionPid(sequelize)).to.not.equal(originalPid); + }); + }); }); } diff --git a/test/integration/error.test.js b/test/integration/error.test.js index beba2d3c9583..31ce5fb6020f 100644 --- a/test/integration/error.test.js +++ b/test/integration/error.test.js @@ -374,7 +374,7 @@ describe(Support.getTestDialectTeaser('Sequelize Errors'), () => { await expect(User.create({ name: 'jan' })).to.be.rejectedWith(Sequelize.UniqueConstraintError); // And when the model is not passed at all - if (dialect === 'db2') { + if (['db2', 'oracle'].includes(dialect)) { await expect(this.sequelize.query('INSERT INTO "users" ("name") VALUES (\'jan\')')).to.be.rejectedWith(Sequelize.UniqueConstraintError); } else { await expect(this.sequelize.query('INSERT INTO users (name) VALUES (\'jan\')')).to.be.rejectedWith(Sequelize.UniqueConstraintError); diff --git a/test/integration/hooks/hooks.test.js b/test/integration/hooks/hooks.test.js index d205ccb51776..311effe30d9a 100644 --- a/test/integration/hooks/hooks.test.js +++ b/test/integration/hooks/hooks.test.js @@ -403,4 +403,24 @@ describe(Support.getTestDialectTeaser('Hooks'), () => { expect(narutoHook).to.have.been.calledTwice; }); }); + + describe('Sequelize hooks', () => { + it('should run before/afterPoolAcquire hooks', async function() { + if (dialect === 'sqlite') { + return this.skip(); + } + + const beforeHook = sinon.spy(); + const afterHook = sinon.spy(); + + this.sequelize.addHook('beforePoolAcquire', beforeHook); + this.sequelize.addHook('afterPoolAcquire', afterHook); + + await this.sequelize.authenticate(); + + expect(beforeHook).to.have.been.calledOnce; + expect(afterHook).to.have.been.calledOnce; + + }); + }); }); diff --git a/test/integration/include.test.js b/test/integration/include.test.js index ead06dbb2362..298b9ec18462 100644 --- a/test/integration/include.test.js +++ b/test/integration/include.test.js @@ -656,6 +656,11 @@ describe(Support.getTestDialectTeaser('Include'), () => { Sequelize.literal('EXISTS(SELECT 1 FROM SYSIBM.SYSDUMMY1) AS "PostComments.someProperty"'), [Sequelize.literal('EXISTS(SELECT 1 FROM SYSIBM.SYSDUMMY1)'), 'someProperty2'] ]; + } else if (dialect === 'oracle') { + findAttributes = [ + Sequelize.literal('(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END) AS "PostComments.someProperty"'), + [Sequelize.literal('(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END)'), 'someProperty2'] + ]; } else { findAttributes = [ Sequelize.literal('EXISTS(SELECT 1) AS "PostComments.someProperty"'), diff --git a/test/integration/include/findAll.test.js b/test/integration/include/findAll.test.js index 29d9e062a24f..458f1ffc08b7 100644 --- a/test/integration/include/findAll.test.js +++ b/test/integration/include/findAll.test.js @@ -6,6 +6,7 @@ const chai = require('chai'), expect = chai.expect, Support = require('../support'), DataTypes = require('sequelize/lib/data-types'), + dialect = Support.getTestDialect(), _ = require('lodash'), promiseProps = require('p-props'); @@ -122,7 +123,7 @@ describe(Support.getTestDialectTeaser('Include'), () => { { title: 'Pen' }, { title: 'Monitor' } ]); - const products = await Product.findAll(); + const products = await Product.findAll({ order: [['id', 'ASC']] }); const groupMembers = [ { AccUserId: user.id, GroupId: groups[0].id, RankId: ranks[0].id }, { AccUserId: user.id, GroupId: groups[1].id, RankId: ranks[2].id } @@ -359,7 +360,7 @@ describe(Support.getTestDialectTeaser('Include'), () => { Product.bulkCreate([ { title: 'Chair' }, { title: 'Desk' } - ]).then(() => Product.findAll()) + ]).then(() => Product.findAll({ order: [['id', 'ASC']] })) ]); await Promise.all([ GroupMember.bulkCreate([ @@ -1207,7 +1208,7 @@ describe(Support.getTestDialectTeaser('Include'), () => { { title: 'Desk' } ]); - const products = await Product.findAll(); + const products = await Product.findAll({ order: [['id', 'ASC']] }); await Promise.all([ GroupMember.bulkCreate([ { UserId: user.id, GroupId: groups[0].id, RankId: ranks[0].id }, diff --git a/test/integration/include/schema.test.js b/test/integration/include/schema.test.js index 7db23df577d0..b8d7c26bb6a5 100644 --- a/test/integration/include/schema.test.js +++ b/test/integration/include/schema.test.js @@ -127,7 +127,7 @@ describe(Support.getTestDialectTeaser('Includes with schemas'), () => { { title: 'Bed' }, { title: 'Pen' }, { title: 'Monitor' } - ]).then(() => Product.findAll()) + ]).then(() => Product.findAll({ order: [['id', 'ASC']] })) ]); const groupMembers = [ { AccUserId: user.id, GroupId: groups[0].id, RankId: ranks[0].id }, @@ -248,7 +248,7 @@ describe(Support.getTestDialectTeaser('Includes with schemas'), () => { Product.bulkCreate([ { title: 'Chair' }, { title: 'Desk' } - ]).then(() => Product.findAll()) + ]).then(() => Product.findAll({ order: [['id', 'ASC']] })) ]); await Promise.all([ GroupMember.bulkCreate([ @@ -936,7 +936,7 @@ describe(Support.getTestDialectTeaser('Includes with schemas'), () => { Product.bulkCreate([ { title: 'Chair' }, { title: 'Desk' } - ]).then(() => Product.findAll()) + ]).then(() => Product.findAll({ order: [['id', 'ASC']] })) ]); await Promise.all([ GroupMember.bulkCreate([ diff --git a/test/integration/instance/save.test.js b/test/integration/instance/save.test.js index 79cbcb9e555a..3dca090c0e23 100644 --- a/test/integration/instance/save.test.js +++ b/test/integration/instance/save.test.js @@ -401,6 +401,14 @@ describe(Support.getTestDialectTeaser('Instance'), () => { expect(userAfterUpdate.username).to.equal('$SEQUELIZE'); }); + it('updates with function that contains multiple escaped dollar symbols', async function() { + const user = await this.User.create({}); + user.username = this.sequelize.fn('upper', '$sequelize and $sequelize2 and some money $42.69'); + await user.save(); + const userAfterUpdate = await this.User.findByPk(user.id); + expect(userAfterUpdate.username).to.equal('$SEQUELIZE AND $SEQUELIZE2 AND SOME MONEY $42.69'); + }); + describe('without timestamps option', () => { it("doesn't update the updatedAt column", async function() { const User2 = this.sequelize.define('User2', { diff --git a/test/integration/instance/values.test.js b/test/integration/instance/values.test.js index 14f24151adc0..402cfaf68045 100644 --- a/test/integration/instance/values.test.js +++ b/test/integration/instance/values.test.js @@ -122,6 +122,8 @@ describe(Support.getTestDialectTeaser('DAO'), () => { let now = dialect === 'sqlite' ? this.sequelize.fn('', this.sequelize.fn('datetime', 'now')) : this.sequelize.fn('NOW'); if (dialect === 'mssql') { now = this.sequelize.fn('', this.sequelize.fn('getdate')); + } else if (dialect === 'oracle') { + now = this.sequelize.fn('', this.sequelize.literal('SYSDATE')); } user.set({ d: now, diff --git a/test/integration/json.test.js b/test/integration/json.test.js index 37a511e5d4db..a71edabd60e2 100644 --- a/test/integration/json.test.js +++ b/test/integration/json.test.js @@ -26,7 +26,10 @@ describe('model', () => { it('should tell me that a column is json', async function() { const table = await this.sequelize.queryInterface.describeTable('Users'); // expected for mariadb 10.4 : https://jira.mariadb.org/browse/MDEV-15558 - if (dialect !== 'mariadb') { + // oracledb 19c doesn't support JSON and the DB datatype is BLOB + if (dialect === 'oracle') { + expect(table.emergency_contact.type).to.equal('BLOB'); + } else if (dialect !== 'mariadb') { expect(table.emergency_contact.type).to.equal('JSON'); } }); @@ -40,6 +43,8 @@ describe('model', () => { logging: sql => { if (dialect.match(/^mysql|mariadb/)) { expect(sql).to.include('?'); + } else if (dialect === 'oracle') { + expect(sql).to.include(':1'); } else { expect(sql).to.include('$1'); } @@ -196,6 +201,19 @@ describe('model', () => { expect(user.username).to.equal('anna'); }); + it('should be able to store strings', async function() { + if (dialect === 'oracle') { + const dbVersion = this.sequelize.options.databaseVersion; + // Oracle DB below 21c doesn't recognize a string as a valid json + if (dbVersion.localeCompare('21.0.0.0') === -1) { + this.skip(); + } + } + await this.User.create({ username: 'swen', emergency_contact: 'joe' }); + const user = await this.User.findOne({ where: { username: 'swen' } }); + expect(user.emergency_contact).to.equal('joe'); + }); + it('should be able to store values that require JSON escaping', async function() { const text = 'Multi-line \'$string\' needing "escaping" for $$ and $1 type values'; @@ -264,6 +282,65 @@ describe('model', () => { }); } + if (current.dialect.supports.JSON) { + describe('json cast type SQL injection', () => { + beforeEach(async function() { + this.User = this.sequelize.define('User', { + username: DataTypes.STRING, + metadata: DataTypes.JSON + }); + + this.Secret = this.sequelize.define('Secret', { + key: DataTypes.STRING, + value: DataTypes.STRING + }); + + await this.sequelize.sync({ force: true }); + + await this.User.bulkCreate([ + { username: 'alice', metadata: { role: 'admin', level: 10 } }, + { username: 'bob', metadata: { role: 'user', level: 5 } } + ]); + + await this.Secret.bulkCreate([ + { key: 'api_key', value: 'sk-secret-12345' } + ]); + }); + + it('should reject WHERE bypass via OR 1=1 injection in JSON cast type', async function() { + await expect(this.User.findAll({ + where: { metadata: { 'role::text) OR 1=1--': 'anything' } } + })).to.be.rejectedWith(Error, /Invalid cast type/); + }); + + it('should reject UNION-based cross-table data exfiltration via JSON cast type', async function() { + await expect(this.User.findAll({ + where: { + metadata: { + ['role::text) AND 0 UNION SELECT id,key,value,null,null FROM Secrets--']: 'x' + } + }, + raw: true + })).to.be.rejectedWith(Error, /Invalid cast type/); + }); + + it('should still allow legitimate JSON queries with valid cast types', async function() { + const users = await this.User.findAll({ + where: { metadata: { level: 10 } } + }); + expect(users).to.have.length(1); + expect(users[0].username).to.equal('alice'); + }); + + it('should still allow legitimate JSON queries with valid :: cast notation', async function() { + const users = await this.User.findAll({ + where: { metadata: { 'level::integer': { [Sequelize.Op.gt]: 3 } } } + }); + expect(users).to.have.length(2); + }); + }); + } + if (current.dialect.supports.JSONB) { describe('jsonb', () => { beforeEach(async function() { diff --git a/test/integration/model.test.js b/test/integration/model.test.js index 120c2124a85b..ad56c5c856f0 100644 --- a/test/integration/model.test.js +++ b/test/integration/model.test.js @@ -239,7 +239,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { title: { type: Sequelize.STRING(50), allowNull: false, - defaultValue: '' + // Oracle dialect doesn't support empty string in a non-null column + defaultValue: dialect === 'oracle' ? 'A' : '' } }, { setterMethods: { @@ -250,7 +251,11 @@ describe(Support.getTestDialectTeaser('Model'), () => { await Task.sync({ force: true }); const record = await Task.build().save(); expect(record.title).to.be.a('string'); - expect(record.title).to.equal(''); + if (dialect === 'oracle') { + expect(record.title).to.equal('A'); + } else { + expect(record.title).to.equal(''); + } expect(titleSetter.notCalled).to.be.ok; // The setter method should not be invoked for default values }); @@ -540,6 +545,24 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(idx3.fields).to.deep.equal([ { attribute: 'fieldD', length: undefined, order: undefined, collate: undefined } ]); + } else if (dialect === 'oracle') { + primary = args[0]; + idx1 = args[1]; + idx2 = args[2]; + idx3 = args[3]; + + expect(idx1.fields).to.deep.equal([ + { attribute: 'fieldB', length: undefined, order: 'ASC', collate: undefined }, + { attribute: 'fieldA', length: undefined, order: 'ASC', collate: undefined } + ]); + + expect(idx2.fields).to.deep.equal([ + { attribute: 'fieldC', length: undefined, order: 'ASC', collate: undefined } + ]); + + expect(idx3.fields).to.deep.equal([ + { attribute: 'fieldD', length: undefined, order: 'ASC', collate: undefined } + ]); } else { // And finally mysql returns the primary first, and then the rest in the order they were defined primary = args[0]; @@ -989,7 +1012,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { fields: ['secretValue'], logging(sql) { test = true; - if (dialect === 'mssql') { + if (['mssql', 'oracle'].includes(dialect)) { expect(sql).to.not.contain('createdAt'); } else { expect(sql).to.match(/UPDATE\s+[`"]+User1s[`"]+\s+SET\s+[`"]+secretValue[`"]=(\$1|\?),[`"]+updatedAt[`"]+=(\$2|\?)\s+WHERE [`"]+id[`"]+\s=\s(\$3|\?)/); @@ -1627,15 +1650,15 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(await User.findOne({ where: { username: 'Bob' } })).to.be.null; const tobi = await User.findOne({ where: { username: 'Tobi' } }); await tobi.destroy(); - let sql = dialect === 'db2' ? 'SELECT * FROM "paranoidusers" WHERE "username"=\'Tobi\'' : 'SELECT * FROM paranoidusers WHERE username=\'Tobi\''; + let sql = ['db2', 'oracle'].includes(dialect) ? 'SELECT * FROM "paranoidusers" WHERE "username"=\'Tobi\'' : 'SELECT * FROM paranoidusers WHERE username=\'Tobi\''; let result = await this.sequelize.query(sql, { plain: true }); expect(result.username).to.equal('Tobi'); await User.destroy({ where: { username: 'Tony' } }); - sql = dialect === 'db2' ? 'SELECT * FROM "paranoidusers" WHERE "username"=\'Tony\'' : 'SELECT * FROM paranoidusers WHERE username=\'Tony\''; + sql = ['db2', 'oracle'].includes(dialect) ? 'SELECT * FROM "paranoidusers" WHERE "username"=\'Tony\'' : 'SELECT * FROM paranoidusers WHERE username=\'Tony\''; result = await this.sequelize.query(sql, { plain: true }); expect(result.username).to.equal('Tony'); await User.destroy({ where: { username: ['Tony', 'Max'] }, force: true }); - sql = dialect === 'db2' ? 'SELECT * FROM "paranoidusers"' : 'SELECT * FROM paranoidusers'; + sql = ['db2', 'oracle'].includes(dialect) ? 'SELECT * FROM "paranoidusers"' : 'SELECT * FROM paranoidusers'; const [users] = await this.sequelize.query(sql, { raw: true }); expect(users).to.have.length(1); expect(users[0].username).to.equal('Tobi'); @@ -1813,7 +1836,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(count.find(i => i.data === 'B')).to.deep.equal({ data: 'B', count: 1 }); }); - if (dialect !== 'mssql' && dialect !== 'db2') { + if (!['mssql', 'db2', 'oracle'].includes(dialect)) { describe('aggregate', () => { it('allows grouping by aliased attribute', async function() { await this.User.aggregate('id', 'count', { @@ -2100,6 +2123,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { db2: 10, mariadb: 3, mysql: 1, + oracle: 2, sqlite: 1 }; expect(schemas).to.have.length(expectedLengths[dialect]); @@ -2150,7 +2174,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { test++; expect(sql).to.not.contain('special'); } - else if (['mysql', 'mssql', 'mariadb', 'db2'].includes(dialect)) { + else if (['mysql', 'mssql', 'mariadb', 'db2', 'oracle'].includes(dialect)) { test++; expect(sql).to.not.contain('special'); } @@ -2169,7 +2193,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { test++; expect(sql).to.contain('special'); } - else if (['mysql', 'mssql', 'mariadb', 'db2'].includes(dialect)) { + else if (['mysql', 'mssql', 'mariadb', 'db2', 'oracle'].includes(dialect)) { test++; expect(sql).to.contain('special'); } @@ -2195,7 +2219,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { UserPub.hasMany(ItemPub, { foreignKeyConstraint: true }); - if (['postgres', 'mssql', 'db2', 'mariadb'].includes(dialect)) { + if (['postgres', 'mssql', 'db2', 'mariadb', 'oracle'].includes(dialect)) { await Support.dropTestSchemas(this.sequelize); await this.sequelize.queryInterface.createSchema('prefix'); } @@ -2211,6 +2235,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(sql).to.match(/REFERENCES\s+"prefix"\."UserPubs" \("id"\)/); } else if (dialect === 'mssql') { expect(sql).to.match(/REFERENCES\s+\[prefix\]\.\[UserPubs\] \(\[id\]\)/); + } else if (dialect === 'oracle') { + expect(sql).to.match(/REFERENCES\s+"prefix"."UserPubs" \("id"\)/); } else if (dialect === 'mariadb') { expect(sql).to.match(/REFERENCES\s+`prefix`\.`UserPubs` \(`id`\)/); } else { @@ -2241,6 +2267,9 @@ describe(Support.getTestDialectTeaser('Model'), () => { } else if (dialect === 'mariadb') { expect(this.UserSpecialSync.getTableName().toString()).to.equal('`special`.`UserSpecials`'); expect(UserPublic.indexOf('INSERT INTO `UserPublics`')).to.be.above(-1); + } else if (dialect === 'oracle') { + expect(this.UserSpecialSync.getTableName().toString()).to.equal('"special"."UserSpecials"'); + expect(UserPublic.indexOf('INSERT INTO "UserPublics"')).to.be.above(-1); } else { expect(this.UserSpecialSync.getTableName().toString()).to.equal('`special.UserSpecials`'); expect(UserPublic).to.include('INSERT INTO `UserPublics`'); @@ -2257,6 +2286,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(UserSpecial).to.include('INSERT INTO `special.UserSpecials`'); } else if (dialect === 'mssql') { expect(UserSpecial).to.include('INSERT INTO [special].[UserSpecials]'); + } else if (dialect === 'oracle') { + expect(UserSpecial).to.include('INSERT INTO "special"."UserSpecials"'); } else if (dialect === 'mariadb') { expect(UserSpecial).to.include('INSERT INTO `special`.`UserSpecials`'); } else { @@ -2272,6 +2303,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(user).to.include('UPDATE "special"."UserSpecials"'); } else if (dialect === 'mssql') { expect(user).to.include('UPDATE [special].[UserSpecials]'); + } else if (dialect === 'oracle') { + expect(user).to.include('UPDATE "special"."UserSpecials"'); } else if (dialect === 'mariadb') { expect(user).to.include('UPDATE `special`.`UserSpecials`'); } else { @@ -2306,21 +2339,14 @@ describe(Support.getTestDialectTeaser('Model'), () => { Post.belongsTo(this.Author); // The posts table gets dropped in the before filter. - await Post.sync({ logging: _.once(sql => { - if (dialect === 'postgres') { - expect(sql).to.match(/"authorId" INTEGER REFERENCES "authors" \("id"\)/); - } else if (['mysql', 'mariadb'].includes(dialect)) { - expect(sql).to.match(/FOREIGN KEY \(`authorId`\) REFERENCES `authors` \(`id`\)/); - } else if (dialect === 'db2') { - expect(sql).to.match(/FOREIGN KEY \("authorId"\) REFERENCES "authors" \("id"\)/); - } else if (dialect === 'mssql') { - expect(sql).to.match(/FOREIGN KEY \(\[authorId\]\) REFERENCES \[authors\] \(\[id\]\)/); - } else if (dialect === 'sqlite') { - expect(sql).to.match(/`authorId` INTEGER REFERENCES `authors` \(`id`\)/); - } else { - throw new Error('Undefined dialect!'); - } - }) }); + await Post.sync(); + + const foreignKeys = await this.sequelize.queryInterface.getForeignKeyReferencesForTable(Post.getTableName()); + + expect(foreignKeys.length).to.eq(1); + expect(foreignKeys[0].columnName).to.eq('authorId'); + expect(foreignKeys[0].referencedTableName).to.eq('authors'); + expect(foreignKeys[0].referencedColumnName).to.eq('id'); }); it('uses a table name as a string and references the author table', async function() { @@ -2332,21 +2358,14 @@ describe(Support.getTestDialectTeaser('Model'), () => { Post.belongsTo(this.Author); // The posts table gets dropped in the before filter. - await Post.sync({ logging: _.once(sql => { - if (dialect === 'postgres') { - expect(sql).to.match(/"authorId" INTEGER REFERENCES "authors" \("id"\)/); - } else if (['mysql', 'mariadb'].includes(dialect)) { - expect(sql).to.match(/FOREIGN KEY \(`authorId`\) REFERENCES `authors` \(`id`\)/); - } else if (dialect === 'db2') { - expect(sql).to.match(/FOREIGN KEY \("authorId"\) REFERENCES "authors" \("id"\)/); - } else if (dialect === 'sqlite') { - expect(sql).to.match(/`authorId` INTEGER REFERENCES `authors` \(`id`\)/); - } else if (dialect === 'mssql') { - expect(sql).to.match(/FOREIGN KEY \(\[authorId\]\) REFERENCES \[authors\] \(\[id\]\)/); - } else { - throw new Error('Undefined dialect!'); - } - }) }); + await Post.sync(); + + const foreignKeys = await this.sequelize.queryInterface.getForeignKeyReferencesForTable(Post.getTableName()); + + expect(foreignKeys.length).to.eq(1); + expect(foreignKeys[0].columnName).to.eq('authorId'); + expect(foreignKeys[0].referencedTableName).to.eq('authors'); + expect(foreignKeys[0].referencedColumnName).to.eq('id'); }); it('emits an error event as the referenced table name is invalid', async function() { @@ -2387,6 +2406,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(err.message).to.match(/Could not create constraint/); } else if (dialect === 'db2') { expect(err.message).to.match(/ is an undefined name/); + } else if (dialect === 'oracle') { + expect(err.message).to.match(/^ORA-00942:/); } else { throw new Error('Undefined dialect!'); } diff --git a/test/integration/model/attributes/field.test.js b/test/integration/model/attributes/field.test.js index 15a0f9afca8d..fb9221a01a47 100644 --- a/test/integration/model/attributes/field.test.js +++ b/test/integration/model/attributes/field.test.js @@ -468,6 +468,11 @@ describe(Support.getTestDialectTeaser('Model'), () => { Sequelize.literal('1 AS "someProperty"'), [Sequelize.literal('1'), 'someProperty2'] ]; + } else if (dialect === 'oracle') { + findAttributes = [ + Sequelize.literal('(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END) AS "someProperty"'), + [Sequelize.literal('(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END)'), 'someProperty2'] + ]; } else { findAttributes = [ Sequelize.literal('EXISTS(SELECT 1) AS "someProperty"'), diff --git a/test/integration/model/attributes/types.test.js b/test/integration/model/attributes/types.test.js index 4ee1dc16774f..7267dbbd71a2 100644 --- a/test/integration/model/attributes/types.test.js +++ b/test/integration/model/attributes/types.test.js @@ -103,6 +103,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { boolQuery = 'CAST(CASE WHEN EXISTS(SELECT 1) THEN 1 ELSE 0 END AS BIT) AS "someBoolean"'; } else if (dialect === 'db2') { boolQuery = '1 AS "someBoolean"'; + } else if (dialect === 'oracle') { + boolQuery = '(CASE WHEN EXISTS(SELECT 1 FROM DUAL) THEN 1 ELSE 0 END) AS "someBoolean"'; } const post = await Post.findOne({ attributes: ['id', 'text', Sequelize.literal(boolQuery)] }); diff --git a/test/integration/model/bulk-create.test.js b/test/integration/model/bulk-create.test.js index 4a40ca992312..76394a13da94 100644 --- a/test/integration/model/bulk-create.test.js +++ b/test/integration/model/bulk-create.test.js @@ -64,7 +64,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { await transaction.rollback(); }); } - + it('should not alter options', async function() { const User = this.sequelize.define('User'); await User.sync({ force: true }); @@ -158,7 +158,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { style: 'ipa' }], { logging(sql) { - if (dialect === 'postgres') { + if (['postgres', 'oracle'].includes(dialect)) { expect(sql).to.include('INSERT INTO "Beers" ("id","style","createdAt","updatedAt") VALUES (DEFAULT'); } else if (dialect === 'db2') { expect(sql).to.include('INSERT INTO "Beers" ("style","createdAt","updatedAt") VALUES'); @@ -732,6 +732,364 @@ describe(Support.getTestDialectTeaser('Model'), () => { this.User.bulkCreate(data, { updateOnDuplicate: [] }) ).to.be.rejectedWith('updateOnDuplicate option only supports non-empty array.'); }); + + if (current.dialect.supports.inserts.conflictFields) { + it('should respect the conflictAttributes option', async function() { + const Permissions = this.sequelize.define( + 'permissions', + { + userId: { + type: DataTypes.INTEGER, + allowNull: false, + field: 'user_id' + }, + permissions: { + type: new DataTypes.ENUM('owner', 'admin', 'member'), + allowNull: false, + default: 'member' + } + }, + { + timestamps: false + } + ); + + await Permissions.sync({ force: true }); + + // We don't want to create this index with the table, since we don't want our sequelize instance + // to know it exists. This prevents it from being inferred. + await this.sequelize.queryInterface.addIndex( + 'permissions', + ['user_id'], + { + unique: true + } + ); + + const initialPermissions = [ + { + userId: 1, + permissions: 'member' + }, + { + userId: 2, + permissions: 'admin' + }, + { + userId: 3, + permissions: 'owner' + } + ]; + + const initialResults = await Permissions.bulkCreate(initialPermissions, { + conflictAttributes: ['userId'], + updateOnDuplicate: ['permissions'] + }); + + expect(initialResults.length).to.eql(3); + + for (let i = 0; i < 3; i++) { + const result = initialResults[i]; + const exp = initialPermissions[i]; + + expect(result).to.not.eql(null); + expect(result.userId).to.eql(exp.userId); + expect(result.permissions).to.eql(exp.permissions); + } + + const newPermissions = [ + { + userId: 1, + permissions: 'owner' + }, + { + userId: 2, + permissions: 'member' + }, + { + userId: 3, + permissions: 'admin' + } + ]; + + const newResults = await Permissions.bulkCreate(newPermissions, { + conflictAttributes: ['userId'], + updateOnDuplicate: ['permissions'] + }); + + expect(newResults.length).to.eql(3); + + for (let i = 0; i < 3; i++) { + const result = newResults[i]; + const exp = newPermissions[i]; + + expect(result).to.not.eql(null); + expect(result.id).to.eql(initialResults[i].id); + expect(result.userId).to.eql(exp.userId); + expect(result.permissions).to.eql(exp.permissions); + } + }); + + describe('conflictWhere', () => { + const Memberships = current.define( + 'memberships', + { + // ID of the member (no foreign key constraint for testing purposes) + user_id: DataTypes.INTEGER, + // ID of what the member is a member of + foreign_id: DataTypes.INTEGER, + time_deleted: DataTypes.DATE + }, + { + createdAt: false, + updatedAt: false, + deletedAt: 'time_deleted', + indexes: [ + { + fields: ['user_id', 'foreign_id'], + unique: true, + where: { time_deleted: null } + } + ] + } + ); + + const options = { + conflictWhere: { time_deleted: null }, + conflictAttributes: ['user_id', 'foreign_id'], + updateOnDuplicate: ['user_id', 'foreign_id', 'time_deleted'] + }; + + beforeEach(() => Memberships.sync({ force: true })); + + it('should insert items with conflictWhere', async () => { + const memberships = new Array(10).fill().map((_, i) => ({ + user_id: i + 1, + foreign_id: i + 20, + time_deleted: null + })); + + const results = await Memberships.bulkCreate( + memberships, + options + ); + + for (let i = 0; i < 10; i++) { + expect(results[i].user_id).to.eq(memberships[i].user_id); + expect(results[i].team_id).to.eq(memberships[i].team_id); + expect(results[i].time_deleted).to.eq(null); + } + }); + + it('should not conflict with soft deleted memberships', async () => { + const memberships = new Array(10).fill().map((_, i) => ({ + user_id: i + 1, + foreign_id: i + 20, + time_deleted: new Date() + })); + + let results = await Memberships.bulkCreate(memberships, options); + + for (let i = 0; i < 10; i++) { + expect(results[i].user_id).to.eq(memberships[i].user_id); + expect(results[i].team_id).to.eq(memberships[i].team_id); + expect(results[i].time_deleted).to.not.eq(null); + } + + results = await Memberships.bulkCreate( + memberships.map(membership => ({ + ...membership, + time_deleted: null + })), + options + ); + + for (let i = 0; i < 10; i++) { + expect(results[i].user_id).to.eq(memberships[i].user_id); + expect(results[i].team_id).to.eq(memberships[i].team_id); + expect(results[i].time_deleted).to.eq(null); + } + + const count = await Memberships.count(); + + expect(count).to.eq(20); + }); + + it('should upsert existing memberships', async () => { + const memberships = new Array(10).fill().map((_, i) => ({ + user_id: i + 1, + foreign_id: i + 20, + time_deleted: i % 2 ? new Date() : null + })); + + let results = await Memberships.bulkCreate(memberships, options); + + for (let i = 0; i < 10; i++) { + expect(results[i].user_id).to.eq(memberships[i].user_id); + expect(results[i].team_id).to.eq(memberships[i].team_id); + if (i % 2) { + expect(results[i].time_deleted).to.not.eq(null); + } else { + expect(results[i].time_deleted).to.eq(null); + } + } + + for (const membership of memberships) { + membership.time_deleted; + } + + results = await Memberships.bulkCreate( + memberships.map(membership => ({ + ...membership, + time_deleted: null + })), + options + ); + + for (let i = 0; i < 10; i++) { + expect(results[i].user_id).to.eq(memberships[i].user_id); + expect(results[i].team_id).to.eq(memberships[i].team_id); + expect(results[i].time_deleted).to.eq(null); + } + + const count = await Memberships.count({ paranoid: false }); + + expect(count).to.eq(15); + }); + }); + + if ( + current.dialect.supports.inserts.onConflictWhere + ) { + describe('conflictWhere', () => { + const Memberships = current.define( + 'memberships', + { + // ID of the member (no foreign key constraint for testing purposes) + user_id: DataTypes.INTEGER, + // ID of what the member is a member of + foreign_id: DataTypes.INTEGER, + time_deleted: DataTypes.DATE + }, + { + createdAt: false, + updatedAt: false, + deletedAt: 'time_deleted', + indexes: [ + { + fields: ['user_id', 'foreign_id'], + unique: true, + where: { time_deleted: null } + } + ] + } + ); + + const options = { + conflictWhere: { time_deleted: null }, + conflictAttributes: ['user_id', 'foreign_id'], + updateOnDuplicate: ['user_id', 'foreign_id', 'time_deleted'] + }; + + beforeEach(() => Memberships.sync({ force: true })); + + it('should insert items with conflictWhere', async () => { + const memberships = new Array(10).fill().map((_, i) => ({ + user_id: i + 1, + foreign_id: i + 20, + time_deleted: null + })); + + const results = await Memberships.bulkCreate( + memberships, + options + ); + + for (let i = 0; i < 10; i++) { + expect(results[i].user_id).to.eq(memberships[i].user_id); + expect(results[i].team_id).to.eq(memberships[i].team_id); + expect(results[i].time_deleted).to.eq(null); + } + }); + + it('should not conflict with soft deleted memberships', async () => { + const memberships = new Array(10).fill().map((_, i) => ({ + user_id: i + 1, + foreign_id: i + 20, + time_deleted: new Date() + })); + + let results = await Memberships.bulkCreate(memberships, options); + + for (let i = 0; i < 10; i++) { + expect(results[i].user_id).to.eq(memberships[i].user_id); + expect(results[i].team_id).to.eq(memberships[i].team_id); + expect(results[i].time_deleted).to.not.eq(null); + } + + results = await Memberships.bulkCreate( + memberships.map(membership => ({ + ...membership, + time_deleted: null + })), + options + ); + + for (let i = 0; i < 10; i++) { + expect(results[i].user_id).to.eq(memberships[i].user_id); + expect(results[i].team_id).to.eq(memberships[i].team_id); + expect(results[i].time_deleted).to.eq(null); + } + + const count = await Memberships.count(); + + expect(count).to.eq(20); + }); + + it('should upsert existing memberships', async () => { + const memberships = new Array(10).fill().map((_, i) => ({ + user_id: i + 1, + foreign_id: i + 20, + time_deleted: i % 2 ? new Date() : null + })); + + let results = await Memberships.bulkCreate(memberships, options); + + for (let i = 0; i < 10; i++) { + expect(results[i].user_id).to.eq(memberships[i].user_id); + expect(results[i].team_id).to.eq(memberships[i].team_id); + if (i % 2) { + expect(results[i].time_deleted).to.not.eq(null); + } else { + expect(results[i].time_deleted).to.eq(null); + } + } + + for (const membership of memberships) { + membership.time_deleted; + } + + results = await Memberships.bulkCreate( + memberships.map(membership => ({ + ...membership, + time_deleted: null + })), + options + ); + + for (let i = 0; i < 10; i++) { + expect(results[i].user_id).to.eq(memberships[i].user_id); + expect(results[i].team_id).to.eq(memberships[i].team_id); + expect(results[i].time_deleted).to.eq(null); + } + + const count = await Memberships.count({ paranoid: false }); + + expect(count).to.eq(15); + }); + }); + } + } }); } diff --git a/test/integration/model/create.test.js b/test/integration/model/create.test.js index 137812185a2d..c89e8804f882 100644 --- a/test/integration/model/create.test.js +++ b/test/integration/model/create.test.js @@ -450,7 +450,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { }); } - (dialect !== 'sqlite' && dialect !== 'mssql' && dialect !== 'db2' ? it : it.skip)('should not fail silently with concurrency higher than pool, a unique constraint and a create hook resulting in mismatched values', async function() { + (!['sqlite', 'mssql', 'db2', 'oracle'].includes(dialect) ? it : it.skip)('should not fail silently with concurrency higher than pool, a unique constraint and a create hook resulting in mismatched values', async function() { const User = this.sequelize.define('user', { username: { type: DataTypes.STRING, @@ -912,6 +912,15 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(user0.secretValue).to.equal('$SEQUELIZE'); }); + it('should escape multiple instances of $ in sequelize functions arguments', async function() { + const user = await this.User.create({ + secretValue: this.sequelize.fn('upper', '$sequelize and $sequelize2 and some money $42.69') + }); + + const user0 = await this.User.findByPk(user.id); + expect(user0.secretValue).to.equal('$SEQUELIZE AND $SEQUELIZE2 AND SOME MONEY $42.69'); + }); + it('should work with a non-id named uuid primary key columns', async function() { const Monkey = this.sequelize.define('Monkey', { monkeyId: { type: DataTypes.UUID, primaryKey: true, defaultValue: DataTypes.UUIDV4, allowNull: false } @@ -1218,7 +1227,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(test).to.be.true; }); - it('should only store the values passed in the whitelist', async function() { + it('should only store the values passed in the whitelist', async function() { // A unique column do not accept NULL in Db2. Unique column must have value in insert statement. const data = { username: 'Peter', secretValue: '42', uniqueName: 'name' }; const fields = dialect === 'db2' ? { fields: ['username', 'uniqueName'] } : { fields: ['username'] }; diff --git a/test/integration/model/findAll/order.test.js b/test/integration/model/findAll/order.test.js index 6f48a73e57db..9775f8a0f428 100644 --- a/test/integration/model/findAll/order.test.js +++ b/test/integration/model/findAll/order.test.js @@ -22,7 +22,8 @@ describe(Support.getTestDialectTeaser('Model'), () => { }); }); - if (current.dialect.name !== 'mssql') { + // Oracle doesn't support operators in Order by clause + if (!['mssql', 'oracle'].includes(current.dialect.name)) { const email = current.dialect.name === 'db2' ? '"email"' : 'email'; it('should work with order: literal()', async function() { const users = await this.User.findAll({ @@ -86,7 +87,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { } it('should not throw on a literal', async function() { - if (current.dialect.name === 'db2') { + if (['db2', 'oracle'].includes(current.dialect.name)) { await this.User.findAll({ order: [ ['id', this.sequelize.literal('ASC, "name" DESC')] diff --git a/test/integration/model/findOne.test.js b/test/integration/model/findOne.test.js index 73c499b15b62..805fa2bc5f58 100644 --- a/test/integration/model/findOne.test.js +++ b/test/integration/model/findOne.test.js @@ -223,6 +223,49 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(u2.name).to.equal('Johnno'); }); + it('finds entries via a bigint primary key called id', async function() { + const UserPrimary = this.sequelize.define('UserWithPrimaryKey', { + id: { type: DataTypes.BIGINT, primaryKey: true }, + name: DataTypes.STRING + }); + + await UserPrimary.sync({ force: true }); + + await UserPrimary.create({ + id: 9007199254740993n, // Number.MAX_SAFE_INTEGER + 2 (cannot be represented exactly as a number in JS) + name: 'Johnno' + }); + + const u2 = await UserPrimary.findByPk(9007199254740993n); + expect(u2.name).to.equal('Johnno'); + + // Getting the value back as bigint is not supported yet: https://github.com/sequelize/sequelize/issues/14296 + // With most dialects we'll receive a string, but in some cases we have to be a bit creative to prove that we did get hold of the right record: + if (dialect === 'db2') { + // ibm_db 2.7.4+ returns BIGINT values as JS numbers, which leads to a loss of precision: + // https://github.com/ibmdb/node-ibm_db/issues/816 + // It means that u2.id comes back as 9007199254740992 here :( + // Hopefully this will be fixed soon. + // For now we can do a separate query where we stringify the value to prove that it did get stored correctly: + const [[{ stringifiedId }]] = await this.sequelize.query(`select "id"::varchar as "stringifiedId" from "${UserPrimary.tableName}" where "id" = 9007199254740993`); + expect(stringifiedId).to.equal('9007199254740993'); + } else if (dialect === 'mariadb') { + // With our current default config, the mariadb driver sends back a Long instance. + // Updating the mariadb dev dep and passing "supportBigInt: true" would get it back as a bigint, + // but that's potentially a big change. + // For now, we'll just stringify the Long and make the comparison: + expect(u2.id.toString()).to.equal('9007199254740993'); + } else if (dialect === 'sqlite') { + // sqlite3 returns a number, so u2.id comes back as 9007199254740992 here: + // https://github.com/TryGhost/node-sqlite3/issues/922 + // For now we can do a separate query where we stringify the value to prove that it did get stored correctly: + const [[{ stringifiedId }]] = await this.sequelize.query(`select cast("id" as text) as "stringifiedId" from "${UserPrimary.tableName}" where "id" = 9007199254740993`); + expect(stringifiedId).to.equal('9007199254740993'); + } else { + expect(u2.id).to.equal('9007199254740993'); + } + }); + it('always honors ZERO as primary key', async function() { const permutations = [ 0, diff --git a/test/integration/model/json.test.js b/test/integration/model/json.test.js index 3eb69501d9fd..b6f26539bd95 100644 --- a/test/integration/model/json.test.js +++ b/test/integration/model/json.test.js @@ -29,22 +29,43 @@ describe(Support.getTestDialectTeaser('Model'), () => { it('findOrCreate supports transactions, json and locks', async function() { const transaction = await current.transaction(); - await this.Event.findOrCreate({ - where: { + const data = { json: { some: { input: 'Hello' } } }, - defaults: { + default_values = { json: { some: { input: 'Hello' }, input: [1, 2, 3] }, data: { some: { input: 'There' }, input: [4, 5, 6] } - }, - transaction, - lock: transaction.LOCK.UPDATE, - logging: sql => { - if (sql.includes('SELECT') && !sql.includes('CREATE')) { - expect(sql.includes('FOR UPDATE')).to.be.true; + }; + + if (current.options.dialect !== 'oracle') { + await this.Event.findOrCreate({ + where: data, + defaults: default_values, + transaction, + lock: transaction.LOCK.UPDATE, + logging: sql => { + if (sql.includes('SELECT') && !sql.includes('CREATE')) { + expect(sql.includes('FOR UPDATE')).to.be.true; + } } + }); + } else { + const events = await this.Event.findAll({ + where: data, + lock: transaction.LOCK.UPDATE, + transaction, + logging: sql => { + if (sql.includes('SELECT') && !sql.includes('CREATE')) { + expect(sql.includes('FOR UPDATE')).to.be.true; + } + } + }); + if (events.length === 0) { + await this.Event.create(default_values, { + transaction + }); } - }); + } const count = await this.Event.count(); expect(count).to.equal(0); diff --git a/test/integration/model/sync.test.js b/test/integration/model/sync.test.js index 09450be58f8d..a7a3ffd918fc 100644 --- a/test/integration/model/sync.test.js +++ b/test/integration/model/sync.test.js @@ -1,11 +1,13 @@ 'use strict'; const chai = require('chai'), - Sequelize = require('sequelize'), + { Sequelize, Deferrable, DataTypes } = require('sequelize'), expect = chai.expect, Support = require('../support'), dialect = Support.getTestDialect(); +const sequelize = Support.sequelize; + describe(Support.getTestDialectTeaser('Model'), () => { describe('sync', () => { beforeEach(async function() { @@ -153,6 +155,7 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(data.dataValues.name).to.eql('test3'); expect(data.dataValues.age).to.eql('1'); }); + it('should properly create composite index that fails on constraint violation', async function() { const testSync = this.sequelize.define('testSync', { name: Sequelize.STRING, @@ -169,21 +172,118 @@ describe(Support.getTestDialectTeaser('Model'), () => { } }); - it('should properly alter tables when there are foreign keys', async function() { - const foreignKeyTestSyncA = this.sequelize.define('foreignKeyTestSyncA', { - dummy: Sequelize.STRING - }); + it('supports creating tables with cyclic associations', async () => { + const A = sequelize.define('A', {}, { timestamps: false }); + const B = sequelize.define('B', {}, { timestamps: false }); - const foreignKeyTestSyncB = this.sequelize.define('foreignKeyTestSyncB', { - dummy: Sequelize.STRING + // These models both have a foreign key that references the other model. + // Sequelize should be able to create them. + A.belongsTo(B, { foreignKey: { allowNull: false } }); + B.belongsTo(A, { foreignKey: { allowNull: false } }); + + await sequelize.sync(); + + const [aFks, bFks] = await Promise.all([ + sequelize.queryInterface.getForeignKeyReferencesForTable(A.getTableName()), + sequelize.queryInterface.getForeignKeyReferencesForTable(B.getTableName()) + ]); + + expect(aFks.length).to.eq(1); + expect(aFks[0].referencedTableName).to.eq('Bs'); + expect(aFks[0].referencedColumnName).to.eq('id'); + expect(aFks[0].columnName).to.eq('BId'); + + expect(bFks.length).to.eq(1); + expect(bFks[0].referencedTableName).to.eq('As'); + expect(bFks[0].referencedColumnName).to.eq('id'); + expect(bFks[0].columnName).to.eq('AId'); + }); + + it('supports creating two identically named tables in different schemas', async () => { + await sequelize.queryInterface.createSchema('custom_schema'); + + const Model1 = sequelize.define('A1', {}, { schema: 'custom_schema', tableName: 'a', timestamps: false }); + const Model2 = sequelize.define('A2', {}, { tableName: 'a', timestamps: false }); + + await Model1.sync(); + await Model2.sync(); + + await Model1.create(); + await Model2.create(); + }); + + describe('with { alter: true }', () => { + it('should properly alter tables when there are foreign keys', async function() { + const foreignKeyTestSyncA = this.sequelize.define('foreignKeyTestSyncA', { + dummy: Sequelize.STRING + }); + + const foreignKeyTestSyncB = this.sequelize.define('foreignKeyTestSyncB', { + dummy: Sequelize.STRING + }); + + foreignKeyTestSyncA.hasMany(foreignKeyTestSyncB); + foreignKeyTestSyncB.belongsTo(foreignKeyTestSyncA); + + await this.sequelize.sync({ alter: true }); + await this.sequelize.sync({ alter: true }); }); - foreignKeyTestSyncA.hasMany(foreignKeyTestSyncB); - foreignKeyTestSyncB.belongsTo(foreignKeyTestSyncA); + // TODO: sqlite's foreign_key_list pragma does not return the DEFERRABLE status of the column + // so sync({ alter: true }) cannot know whether the column must be updated. + // so for now, deferrableConstraints is disabled for sqlite (as it's only used in tests) + if (sequelize.dialect.supports.deferrableConstraints) { + it('updates the deferrable property of a foreign key', async () => { + const A = sequelize.define('A', { + BId: { + type: DataTypes.INTEGER, + references: { + deferrable: Deferrable.INITIALLY_IMMEDIATE() + } + } + }); + const B = sequelize.define('B'); - await this.sequelize.sync({ alter: true }); + A.belongsTo(B); - await this.sequelize.sync({ alter: true }); + await sequelize.sync(); + + { + const aFks = await sequelize.queryInterface.getForeignKeyReferencesForTable(A.getTableName()); + + expect(aFks.length).to.eq(1); + expect(aFks[0].deferrable).to.eq(Deferrable.INITIALLY_IMMEDIATE); + } + + A.rawAttributes.BId.references.deferrable = Deferrable.INITIALLY_DEFERRED; + await sequelize.sync({ alter: true }); + + { + const aFks = await sequelize.queryInterface.getForeignKeyReferencesForTable(A.getTableName()); + + expect(aFks.length).to.eq(1); + expect(aFks[0].deferrable).to.eq(Deferrable.INITIALLY_DEFERRED); + } + }); + } + + // TODO add support for db2 and mssql dialects + if (!['db2', 'mssql'].includes(dialect)) { + it('does not recreate existing enums (#7649)', async () => { + sequelize.define('Media', { + type: DataTypes.ENUM([ + 'video', 'audio' + ]) + }); + await sequelize.sync({ alter: true }); + sequelize.define('Media', { + type: DataTypes.ENUM([ + 'image', 'video', 'audio' + ]) + }); + await sequelize.sync({ alter: true }); + }); + } }); describe('indexes', () => { diff --git a/test/integration/model/upsert.test.js b/test/integration/model/upsert.test.js index 072f2797e80e..764ffe1fe293 100644 --- a/test/integration/model/upsert.test.js +++ b/test/integration/model/upsert.test.js @@ -760,6 +760,167 @@ describe(Support.getTestDialectTeaser('Model'), () => { expect(otherMembership.id).to.not.eq(originalMembership.id); }); }); + + if (current.dialect.supports.inserts.onConflictWhere) { + describe('conflictWhere', () => { + const Users = current.define( + 'users', + { + name: DataTypes.STRING, + bio: DataTypes.STRING, + isUnique: DataTypes.BOOLEAN + }, + { + indexes: [ + { + unique: true, + fields: ['name'], + where: { isUnique: true } + } + ] + } + ); + + beforeEach(() => Users.sync({ force: true })); + + it('should insert with no other rows', async () => { + const [newRow] = await Users.upsert( + { + name: 'John', + isUnique: true + }, + { + conflictWhere: { + isUnique: true + } + } + ); + + expect(newRow).to.not.eq(null); + expect(newRow.name).to.eq('John'); + }); + + it('should update with another unique user', async () => { + let [newRow] = await Users.upsert( + { + name: 'John', + isUnique: true, + bio: 'before' + }, + { + conflictWhere: { + isUnique: true + } + } + ); + + expect(newRow).to.not.eq(null); + expect(newRow.name).to.eq('John'); + expect(newRow.bio).to.eq('before'); + + [newRow] = await Users.upsert( + { + name: 'John', + isUnique: true, + bio: 'after' + }, + { + conflictWhere: { + isUnique: true + } + } + ); + + expect(newRow).to.not.eq(null); + expect(newRow.name).to.eq('John'); + expect(newRow.bio).to.eq('after'); + + const rowCount = await Users.count(); + + expect(rowCount).to.eq(1); + }); + + it('allows both unique and non-unique users with the same name', async () => { + let [newRow] = await Users.upsert( + { + name: 'John', + isUnique: true, + bio: 'first' + }, + { + conflictWhere: { + isUnique: true + } + } + ); + + expect(newRow).to.not.eq(null); + expect(newRow.name).to.eq('John'); + expect(newRow.bio).to.eq('first'); + + [newRow] = await Users.upsert( + { + name: 'John', + isUnique: false, + bio: 'second' + }, + { + conflictWhere: { + isUnique: true + } + } + ); + + expect(newRow).to.not.eq(null); + expect(newRow.name).to.eq('John'); + expect(newRow.bio).to.eq('second'); + + const rowCount = await Users.count(); + + expect(rowCount).to.eq(2); + }); + + it('allows for multiple unique users with different names', async () => { + let [newRow] = await Users.upsert( + { + name: 'John', + isUnique: true, + bio: 'first' + }, + { + conflictWhere: { + isUnique: true + } + } + ); + + expect(newRow).to.not.eq(null); + expect(newRow.name).to.eq('John'); + expect(newRow.bio).to.eq('first'); + + [newRow] = await Users.upsert( + { + name: 'Bob', + isUnique: false, + bio: 'second' + }, + { + conflictWhere: { + isUnique: true + } + } + ); + + expect(newRow).to.not.eq(null); + expect(newRow.name).to.eq('Bob'); + expect(newRow.bio).to.eq('second'); + + const rowCount = await Users.count(); + + expect(rowCount).to.eq(2); + }); + }); + } } }); } diff --git a/test/integration/pool.test.js b/test/integration/pool.test.js index 98357e7cc679..76bf6a380000 100644 --- a/test/integration/pool.test.js +++ b/test/integration/pool.test.js @@ -14,6 +14,10 @@ function assertSameConnection(newConnection, oldConnection) { expect(oldConnection.processID).to.be.equal(newConnection.processID).and.to.be.ok; break; + case 'oracle': + expect(oldConnection).to.be.equal(newConnection); + break; + case 'mariadb': case 'mysql': expect(oldConnection.threadId).to.be.equal(newConnection.threadId).and.to.be.ok; @@ -48,6 +52,10 @@ function assertNewConnection(newConnection, oldConnection) { expect(oldConnection.connected).to.not.be.ok; break; + case 'oracle': + expect(oldConnection).to.not.be.equal(newConnection); + break; + case 'mssql': // Flaky test expect(newConnection.dummyId).to.not.be.ok; @@ -110,7 +118,7 @@ describe(Support.getTestDialectTeaser('Pooling'), () => { }); it('should obtain new connection when released connection dies inside pool', async () => { - function simulateUnexpectedError(connection) { + async function simulateUnexpectedError(connection) { // should never be returned again if (dialect === 'mssql') { attachMSSQLUniqueId(connection).close(); @@ -118,6 +126,9 @@ describe(Support.getTestDialectTeaser('Pooling'), () => { connection.end(); } else if (dialect === 'db2') { connection.closeSync(); + } else if (dialect === 'oracle') { + // For the Oracle dialect close is an async function + await connection.close(); } else { connection.close(); } @@ -131,7 +142,7 @@ describe(Support.getTestDialectTeaser('Pooling'), () => { const oldConnection = await cm.getConnection(); await cm.releaseConnection(oldConnection); - simulateUnexpectedError(oldConnection); + await simulateUnexpectedError(oldConnection); const newConnection = await cm.getConnection(); assertNewConnection(newConnection, oldConnection); diff --git a/test/integration/query-interface.test.js b/test/integration/query-interface.test.js index d514d192a65a..1bb6ab319e98 100644 --- a/test/integration/query-interface.test.js +++ b/test/integration/query-interface.test.js @@ -38,13 +38,25 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { async function cleanup(sequelize) { if (dialect === 'db2') { await sequelize.query('DROP VIEW V_Fail'); + } else if (dialect === 'oracle') { + const plsql = [ + 'BEGIN', + 'EXECUTE IMMEDIATE', + '\'DROP VIEW V_Fail\';', + 'EXCEPTION WHEN OTHERS THEN', + ' IF SQLCODE != -942 THEN', + ' RAISE;', + ' END IF;', + 'END;' + ].join(' '); + await sequelize.query(plsql); } else { await sequelize.query('DROP VIEW IF EXISTS V_Fail'); } } await this.queryInterface.createTable('my_test_table', { name: DataTypes.STRING }); await cleanup(this.sequelize); - const sql = dialect === 'db2' ? 'CREATE VIEW V_Fail AS SELECT 1 Id FROM SYSIBM.SYSDUMMY1' : 'CREATE VIEW V_Fail AS SELECT 1 Id'; + const sql = dialect === 'db2' ? 'CREATE VIEW V_Fail AS SELECT 1 Id FROM SYSIBM.SYSDUMMY1' : `CREATE VIEW V_Fail AS SELECT 1 Id${ Support.addDualInSelect()}`; await this.sequelize.query(sql); let tableNames = await this.queryInterface.showAllTables(); await cleanup(this.sequelize); @@ -54,7 +66,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(tableNames).to.deep.equal(['my_test_table']); }); - if (dialect !== 'sqlite' && dialect !== 'postgres' && dialect !== 'db2') { + if (!['sqlite', 'postgres', 'db2', 'oracle'].includes(dialect)) { // NOTE: sqlite doesn't allow querying between databases and // postgres requires creating a new connection to create a new table. it('should not show tables in other databases', async function() { @@ -101,7 +113,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { }); await this.queryInterface.renameTable('my_test_table', 'my_test_table_new'); let tableNames = await this.queryInterface.showAllTables(); - if (['mssql', 'mariadb', 'db2'].includes(dialect)) { + if (['mssql', 'mariadb', 'db2', 'oracle'].includes(dialect)) { tableNames = tableNames.map(v => v.tableName); } expect(tableNames).to.contain('my_test_table_new'); @@ -143,7 +155,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { }); await this.queryInterface.dropAllTables({ skip: ['skipme'] }); let tableNames = await this.queryInterface.showAllTables(); - if (['mssql', 'mariadb', 'db2'].includes(dialect)) { + if (['mssql', 'mariadb', 'db2', 'oracle'].includes(dialect)) { tableNames = tableNames.map(v => v.tableName); } expect(tableNames).to.contain('skipme'); @@ -463,6 +475,8 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(Object.keys(foreignKeys[0])).to.have.length(8); } else if (['mysql', 'mariadb', 'mssql'].includes(dialect)) { expect(Object.keys(foreignKeys[0])).to.have.length(12); + } else if (dialect === 'oracle') { + expect(Object.keys(foreignKeys[0])).to.have.length(6); } else { throw new Error(`This test doesn't support ${dialect}`); } @@ -631,7 +645,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { field: 'username' }, onDelete: 'cascade', - onUpdate: 'cascade', + onUpdate: dialect !== 'oracle' ? 'cascade' : null, type: 'foreign key' }); let constraints = await this.queryInterface.showConstraint('posts'); @@ -653,8 +667,11 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { throw new Error('Error not thrown...'); } catch (error) { expect(error).to.be.instanceOf(Sequelize.UnknownConstraintError); - expect(error.table).to.equal('users'); - expect(error.constraint).to.equal('unknown__constraint__name'); + // The Oracle dialect, error messages doesn't have table and constraint information + if (dialect != 'oracle') { + expect(error.table).to.equal('users'); + expect(error.constraint).to.equal('unknown__constraint__name'); + } } }); }); diff --git a/test/integration/query-interface/changeColumn.test.js b/test/integration/query-interface/changeColumn.test.js index a1e2501d9370..41ec3edd609f 100644 --- a/test/integration/query-interface/changeColumn.test.js +++ b/test/integration/query-interface/changeColumn.test.js @@ -48,6 +48,8 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(table.currency.type).to.equal('DOUBLE PRECISION'); } else if (dialect === 'db2') { expect(table.currency.type).to.equal('DOUBLE'); + } else if (dialect === 'oracle') { + expect(table.currency.type).to.equal('BINARY_FLOAT'); } else { expect(table.currency.type).to.equal('FLOAT'); } @@ -82,6 +84,8 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(table.currency.type).to.equal('DOUBLE PRECISION'); } else if (dialect === 'db2') { expect(table.currency.type).to.equal('DOUBLE'); + } else if (dialect === 'oracle') { + expect(table.currency.type).to.equal('BINARY_FLOAT'); } else { expect(table.currency.type).to.equal('FLOAT'); } @@ -223,7 +227,8 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(describedTable.level_id.allowNull).to.not.equal(firstTable.level_id.allowNull); expect(describedTable.level_id.allowNull).to.be.equal(true); }); - if (dialect !== 'db2') { + // For Oracle, comments are not part of table description and are stored differently. + if (!['db2', 'oracle'].includes(dialect)) { it('should change the comment of column', async function() { const describedTable = await this.queryInterface.describeTable({ tableName: 'users' diff --git a/test/integration/query-interface/createTable.test.js b/test/integration/query-interface/createTable.test.js index b8dd42e19bd6..b9133e2ebe45 100644 --- a/test/integration/query-interface/createTable.test.js +++ b/test/integration/query-interface/createTable.test.js @@ -77,7 +77,8 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { break; case 'mariadb': case 'mysql': - case 'db2': + case 'db2': + case 'oracle': // name + email expect(indexes[1].unique).to.be.true; expect(indexes[1].fields[0].attribute).to.equal('name'); diff --git a/test/integration/query-interface/describeTable.test.js b/test/integration/query-interface/describeTable.test.js index 796ce1e10eaa..5c6652784148 100644 --- a/test/integration/query-interface/describeTable.test.js +++ b/test/integration/query-interface/describeTable.test.js @@ -73,6 +73,9 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { let assertVal = 'VARCHAR(255)'; switch (dialect) { + case 'oracle': + assertVal = 'NVARCHAR2'; + break; case 'postgres': assertVal = 'CHARACTER VARYING(255)'; break; @@ -87,6 +90,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(username.allowNull).to.be.true; switch (dialect) { + case 'oracle': case 'sqlite': expect(username.defaultValue).to.be.undefined; break; @@ -102,6 +106,9 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { assertVal = 'TINYINT(1)'; switch (dialect) { + case 'oracle': + assertVal = 'CHAR'; + break; case 'postgres': case 'db2': assertVal = 'BOOLEAN'; @@ -113,6 +120,7 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(isAdmin.type).to.equal(assertVal); expect(isAdmin.allowNull).to.be.true; switch (dialect) { + case 'oracle': case 'sqlite': expect(isAdmin.defaultValue).to.be.undefined; break; @@ -166,5 +174,16 @@ describe(Support.getTestDialectTeaser('QueryInterface'), () => { expect(metalumni.ctrycod.primaryKey).to.eql(false); expect(metalumni.city.primaryKey).to.eql(false); }); + + it('should correctly return the columns when the table contains a dot in the name', async function() { + const User = this.sequelize.define('my.user', { + name: DataTypes.STRING + }, { freezeTableName: true }); + + await User.sync({ force: true }); + const metadata = await this.queryInterface.describeTable('my.user'); + + expect(metadata).to.haveOwnProperty('name'); + }); }); }); diff --git a/test/integration/sequelize.test.js b/test/integration/sequelize.test.js index 59361493ecd6..b6c91120d292 100644 --- a/test/integration/sequelize.test.js +++ b/test/integration/sequelize.test.js @@ -12,7 +12,7 @@ const sinon = require('sinon'); const current = Support.sequelize; const qq = str => { - if (['postgres', 'mssql', 'db2'].includes(dialect)) { + if (['postgres', 'mssql', 'db2', 'oracle'].includes(dialect)) { return `"${str}"`; } if (['mysql', 'mariadb', 'sqlite'].includes(dialect)) { @@ -123,13 +123,14 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { .sequelizeWithInvalidConnection .authenticate(); } catch (err) { - console.log(err); expect( err.message.includes('connect ECONNREFUSED') || err.message.includes('invalid port number') || err.message.match(/should be >=? 0 and < 65536/) || err.message.includes('Login failed for user') || err.message.includes('A communication error has been detected') || + err.message.includes('ORA-12545') || + err.message.includes('ORA-12541') || err.message.includes('must be > 0 and < 65536') ).to.be.ok; } @@ -229,6 +230,17 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { }); }); + describe('modelManager', () => { + it('allows to find a model using a callback', function() { + const project = this.sequelize.define('Project', { + name: DataTypes.STRING + }); + + const model = this.sequelize.modelManager.findModel(m => m.name.toLowerCase() === 'project'); + expect(model).to.equal(project); + }); + }); + describe('set', () => { it('should be configurable with global functions', function() { const defaultSetterMethod = sinon.spy(), @@ -362,7 +374,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { const Photo = this.sequelize.define('Foto', { name: DataTypes.STRING }, { tableName: 'photos' }); await Photo.sync({ force: true }); let tableNames = await this.sequelize.getQueryInterface().showAllTables(); - if (['mssql', 'mariadb', 'db2'].includes(dialect)) { + if (['mssql', 'mariadb', 'db2', 'oracle'].includes(dialect)) { tableNames = tableNames.map(v => v.tableName); } expect(tableNames).to.include('photos'); @@ -452,6 +464,8 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { expect(err.message).to.equal('Login failed for user \'bar\'.'); } else if (dialect === 'db2') { expect(err.message).to.include('A communication error has been detected'); + } else if (dialect === 'oracle') { + expect(err.message).to.include('NJS-007'); } else { expect(err.message.toString()).to.match(/.*Access denied.*/); } @@ -721,7 +735,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { const TransactionTest = this.sequelizeWithTransaction.define('TransactionTest', { name: DataTypes.STRING }, { timestamps: false }); const count = async transaction => { - const sql = this.sequelizeWithTransaction.getQueryInterface().queryGenerator.selectQuery('TransactionTests', { attributes: [['count(*)', 'cnt']] }); + const sql = this.sequelizeWithTransaction.getQueryInterface().queryGenerator.selectQuery('TransactionTests', { attributes: [[Sequelize.literal('count(*)'), 'cnt']] }); const result = await this.sequelizeWithTransaction.query(sql, { plain: true, transaction }); @@ -744,7 +758,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { const aliasesMapping = new Map([['_0', 'cnt']]); const count = async transaction => { - const sql = this.sequelizeWithTransaction.getQueryInterface().queryGenerator.selectQuery('TransactionTests', { attributes: [['count(*)', 'cnt']] }); + const sql = this.sequelizeWithTransaction.getQueryInterface().queryGenerator.selectQuery('TransactionTests', { attributes: [[Sequelize.literal('count(*)'), 'cnt']] }); const result = await this.sequelizeWithTransaction.query(sql, { plain: true, transaction, aliasesMapping }); diff --git a/test/integration/sequelize.transaction.test.js b/test/integration/sequelize.transaction.test.js index 22d2f03ba72a..f6fef21a3a48 100644 --- a/test/integration/sequelize.transaction.test.js +++ b/test/integration/sequelize.transaction.test.js @@ -1,5 +1,6 @@ 'use strict'; +const sinon = require('sinon'); const chai = require('chai'), expect = chai.expect, Support = require('./support'), @@ -7,135 +8,177 @@ const chai = require('chai'), current = Support.sequelize, delay = require('delay'); -if (current.dialect.supports.transactions) { +const sequelize = Support.sequelize; +const dialectName = sequelize.dialect.name; - describe(Support.getTestDialectTeaser('Sequelize#transaction'), () => { +describe(Support.getTestDialectTeaser('Sequelize#transaction'), () => { + if (!current.dialect.supports.transactions) { + return; + } - describe('then', () => { - it('gets triggered once a transaction has been successfully committed', async function() { - let called = false; + let stubs = []; + + afterEach(() => { + for (const stub of stubs) { + stub.restore(); + } + + stubs = []; + }); + + describe('Transaction#commit', () => { + it('returns a promise that resolves once the transaction has been committed', async function() { + const t = await this + .sequelize + .transaction(); + + await expect(t.commit()).to.eventually.equal(undefined); + }); + + // we cannot close a sqlite connection, but there also cannot be a network error with sqlite. + // so this test is not necessary for that dialect. + if (dialectName !== 'sqlite') { + it('does not pollute the pool with broken connections if commit fails', async function() { + const initialPoolSize = this.sequelize.connectionManager.pool.size; + + stubs.push(sinon.stub(this.sequelize.queryInterface, 'commitTransaction').rejects(new Error('Oh no, an error!'))); const t = await this .sequelize .transaction(); - await t.commit(); - called = 1; - expect(called).to.be.ok; + await expect(t.commit()).to.be.rejectedWith('Oh no, an error!'); + + // connection should have been destroyed + expect(this.sequelize.connectionManager.pool.size).to.eq(Math.max(0, initialPoolSize - 1)); }); + } + }); + + describe('Transaction#rollback', () => { + it('returns a promise that resolves once the transaction has been rolled back', async function() { + const t = await this + .sequelize + .transaction(); + + expect(t.rollback()).to.eventually.equal(undefined); + }); + + // we cannot close a sqlite connection, but there also cannot be a network error with sqlite. + // so this test is not necessary for that dialect. + if (dialectName !== 'sqlite') { + it('does not pollute the pool with broken connections if the rollback fails', async function() { + const initialPoolSize = this.sequelize.connectionManager.pool.size; - it('gets triggered once a transaction has been successfully rolled back', async function() { - let called = false; + stubs.push(sinon.stub(this.sequelize.queryInterface, 'rollbackTransaction').rejects(new Error('Oh no, an error!'))); const t = await this .sequelize .transaction(); - await t.rollback(); - called = 1; - expect(called).to.be.ok; - }); + await expect(t.rollback()).to.be.rejectedWith('Oh no, an error!'); - if (Support.getTestDialect() !== 'sqlite' && - Support.getTestDialect() !== 'db2') { - it('works for long running transactions', async function() { - const sequelize = await Support.prepareTransactionTest(this.sequelize); - this.sequelize = sequelize; - - this.User = sequelize.define('User', { - name: Support.Sequelize.STRING - }, { timestamps: false }); - - await sequelize.sync({ force: true }); - const t = await this.sequelize.transaction(); - let query = 'select sleep(2);'; - - switch (Support.getTestDialect()) { - case 'postgres': - query = 'select pg_sleep(2);'; - break; - case 'sqlite': - query = 'select sqlite3_sleep(2000);'; - break; - case 'mssql': - query = 'WAITFOR DELAY \'00:00:02\';'; - break; - default: - break; - } + // connection should have been destroyed + expect(this.sequelize.connectionManager.pool.size).to.eq(Math.max(0, initialPoolSize - 1)); + }); + } + }); - await this.sequelize.query(query, { transaction: t }); - await this.User.create({ name: 'foo' }); - await this.sequelize.query(query, { transaction: t }); - await t.commit(); - const users = await this.User.findAll(); - expect(users.length).to.equal(1); - expect(users[0].name).to.equal('foo'); - }); + if (Support.getTestDialect() !== 'sqlite' && Support.getTestDialect() !== 'db2') { + it('works for long running transactions', async function() { + const sequelize = await Support.prepareTransactionTest(this.sequelize); + this.sequelize = sequelize; + + this.User = sequelize.define('User', { + name: Support.Sequelize.STRING + }, { timestamps: false }); + + await sequelize.sync({ force: true }); + const t = await this.sequelize.transaction(); + let query = 'select sleep(2);'; + + switch (Support.getTestDialect()) { + case 'postgres': + query = 'select pg_sleep(2);'; + break; + case 'sqlite': + query = 'select sqlite3_sleep(2000);'; + break; + case 'mssql': + query = 'WAITFOR DELAY \'00:00:02\';'; + break; + case 'oracle': + query = 'BEGIN DBMS_SESSION.sleep(2); END;'; + break; + default: + break; } + + await this.sequelize.query(query, { transaction: t }); + await this.User.create({ name: 'foo' }); + await this.sequelize.query(query, { transaction: t }); + await t.commit(); + const users = await this.User.findAll(); + expect(users.length).to.equal(1); + expect(users[0].name).to.equal('foo'); }); + } + + describe('complex long running example', () => { + it('works with promise syntax', async function() { + const sequelize = await Support.prepareTransactionTest(this.sequelize); + const Test = sequelize.define('Test', { + id: { type: Support.Sequelize.INTEGER, primaryKey: true, autoIncrement: true }, + name: { type: Support.Sequelize.STRING } + }); - describe('complex long running example', () => { - it('works with promise syntax', async function() { - const sequelize = await Support.prepareTransactionTest(this.sequelize); - const Test = sequelize.define('Test', { - id: { type: Support.Sequelize.INTEGER, primaryKey: true, autoIncrement: true }, - name: { type: Support.Sequelize.STRING } - }); + await sequelize.sync({ force: true }); + const transaction = await sequelize.transaction(); + expect(transaction).to.be.instanceOf(Transaction); - await sequelize.sync({ force: true }); - const transaction = await sequelize.transaction(); - expect(transaction).to.be.instanceOf(Transaction); + await Test.create({ name: 'Peter' }, { transaction }); - await Test - .create({ name: 'Peter' }, { transaction }); + await delay(1000); - await delay(1000); + await transaction.commit(); - await transaction - .commit(); + const count = await Test.count(); + expect(count).to.equal(1); + }); + }); + + describe('concurrency: having tables with uniqueness constraints', () => { + beforeEach(async function() { + const sequelize = await Support.prepareTransactionTest(this.sequelize); + this.sequelize = sequelize; - const count = await Test.count(); - expect(count).to.equal(1); + this.Model = sequelize.define('Model', { + name: { type: Support.Sequelize.STRING, unique: true } + }, { + timestamps: false }); + + await this.Model.sync({ force: true }); }); - describe('concurrency', () => { - describe('having tables with uniqueness constraints', () => { - beforeEach(async function() { - const sequelize = await Support.prepareTransactionTest(this.sequelize); - this.sequelize = sequelize; - - this.Model = sequelize.define('Model', { - name: { type: Support.Sequelize.STRING, unique: true } - }, { - timestamps: false - }); - - await this.Model.sync({ force: true }); - }); - - it('triggers the error event for the second transactions', async function() { - const t1 = await this.sequelize.transaction(); - const t2 = await this.sequelize.transaction(); - await this.Model.create({ name: 'omnom' }, { transaction: t1 }); - - await Promise.all([ - (async () => { - try { - return await this.Model.create({ name: 'omnom' }, { transaction: t2 }); - } catch (err) { - expect(err).to.be.ok; - return t2.rollback(); - } - })(), - delay(100).then(() => { - return t1.commit(); - }) - ]); - }); - }); + it('triggers the error event for the second transactions', async function() { + const t1 = await this.sequelize.transaction(); + const t2 = await this.sequelize.transaction(); + await this.Model.create({ name: 'omnom' }, { transaction: t1 }); + + await Promise.all([ + (async () => { + try { + return await this.Model.create({ name: 'omnom' }, { transaction: t2 }); + } catch (err) { + expect(err).to.be.ok; + return t2.rollback(); + } + })(), + delay(100).then(() => { + return t1.commit(); + }) + ]); }); }); - -} +}); diff --git a/test/integration/sequelize/drop.test.js b/test/integration/sequelize/drop.test.js new file mode 100644 index 000000000000..0d88f96a16d7 --- /dev/null +++ b/test/integration/sequelize/drop.test.js @@ -0,0 +1,86 @@ +'use strict'; + +const { Deferrable, DataTypes } = require('sequelize'); +const { sequelize } = require('../support'); + +describe('Sequelize#drop', () => { + it('supports dropping cyclic associations', async () => { + const A = sequelize.define('A', { + BId: { + type: DataTypes.INTEGER, + references: { + deferrable: Deferrable.INITIALLY_IMMEDIATE + } + } + }); + + const B = sequelize.define('B', { + AId: { + type: DataTypes.INTEGER, + references: { + deferrable: Deferrable.INITIALLY_IMMEDIATE + } + } + }); + + // These models both have a foreign key that references the other model. + // Sequelize should be able to create them. + A.belongsTo(B, { foreignKey: { allowNull: false } }); + B.belongsTo(A, { foreignKey: { allowNull: false } }); + + await sequelize.sync(); + + // drop both tables + await sequelize.drop(); + }); + + describe('with schemas', () => { + beforeEach(async () => { + await Promise.all([ + sequelize.createSchema('schemaA'), + sequelize.createSchema('schemaB') + ]); + }); + + afterEach(async () => { + await Promise.all([ + sequelize.dropSchema('schemaA'), + sequelize.dropSchema('schemaB') + ]); + }); + + it('supports schemas when dropping foreign keys for a table', async () => { + sequelize.define('schemaA_A', {}, { + tableName: 'A', + schema: 'schemaA' + }); + + + // External tables, use sequelize interface to create them. + const schemaB_A = sequelize.define('schemaB_A', {}, { + tableName: 'A', + schema: 'schemaB' + }); + + const schemaB_B = sequelize.define('schemaB_B', { + BId: { + type: DataTypes.INTEGER + } + }, { + tableName: 'B', + schema: 'schemaB' + }); + + schemaB_A.belongsTo(schemaB_B, { foreignKey: { allowNull: false } }); + + await sequelize.sync(); + + // Assume "schemaB" models were not created by sequelize and already exist in the database. + sequelize.modelManager.removeModel(schemaB_A); + sequelize.modelManager.removeModel(schemaB_B); + + // Try to drop "schemaA" table. + await sequelize.drop(); + }); + }); +}); diff --git a/test/integration/sequelize/query.test.js b/test/integration/sequelize/query.test.js index 767940b5dbe9..f9f994cd57eb 100644 --- a/test/integration/sequelize/query.test.js +++ b/test/integration/sequelize/query.test.js @@ -10,7 +10,7 @@ const moment = require('moment'); const { DatabaseError, UniqueConstraintError, ForeignKeyConstraintError } = Support.Sequelize; const qq = str => { - if (['postgres', 'mssql', 'db2'].includes(dialect)) { + if (['postgres', 'mssql', 'db2', 'oracle'].includes(dialect)) { return `"${str}"`; } if (['mysql', 'mariadb', 'sqlite'].includes(dialect)) { @@ -19,6 +19,13 @@ const qq = str => { return str; }; +const dateLiteral = str => { + if (dialect === 'oracle') { + return `to_date('${str}','YYYY-MM-DD HH24:MI:SS')`; + } + return `'${str}'`; +}; + describe(Support.getTestDialectTeaser('Sequelize'), () => { describe('query', () => { afterEach(function() { @@ -38,9 +45,9 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { } }); - this.insertQuery = `INSERT INTO ${qq(this.User.tableName)} (username, email_address, ${ + this.insertQuery = `INSERT INTO ${qq(this.User.tableName)} (${qq('username')}, ${qq('email_address')}, ${ qq('createdAt') }, ${qq('updatedAt') - }) VALUES ('john', 'john@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10')`; + }) VALUES ('john', 'john@gmail.com',${dateLiteral('2012-01-01 10:10:10')},${dateLiteral('2012-01-01 10:10:10')})`; if (dialect === 'db2') { this.insertQuery = `INSERT INTO ${qq(this.User.tableName)} ("username", "email_address", ${ qq('createdAt') }, ${qq('updatedAt')}) VALUES ('john', 'john@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10')`; @@ -57,13 +64,29 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { }); it('executes a query if a placeholder value is an array', async function() { - await this.sequelize.query(`INSERT INTO ${qq(this.User.tableName)} (${qq('username')}, ${qq('email_address')}, ` + - `${qq('createdAt')}, ${qq('updatedAt')}) VALUES ?;`, { - replacements: [[ - ['john', 'john@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10'], - ['michael', 'michael@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10'] - ]] - }); + if (dialect === 'oracle') { + await this.sequelize.query( + 'INSERT ' + + `INTO ${qq(this.User.tableName)} (${qq('username')}, ${qq('email_address')}, ` + + `${qq('createdAt')}, ${qq('updatedAt')}) ` + + `with p (${qq('username')}, ${qq('email_address')}, ${qq('createdAt')}, ${qq('updatedAt')}) as ( ` + + 'select ? from dual union all ' + + 'select ? from dual ' + + ') select * from p; ', { + replacements: [ + ['john', 'john@gmail.com', new Date('2012-01-01 10:10:10'), new Date('2012-01-01 10:10:10')], + ['michael', 'michael@gmail.com', new Date('2012-01-01 10:10:10'), new Date('2012-01-01 10:10:10')] + ] + }); + } else { + await this.sequelize.query(`INSERT INTO ${qq(this.User.tableName)} (${qq('username')}, ${qq('email_address')}, ` + + `${qq('createdAt')}, ${qq('updatedAt')}) VALUES ?;`, { + replacements: [[ + ['john', 'john@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10'], + ['michael', 'michael@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10'] + ]] + }); + } const rows = await this.sequelize.query(`SELECT * FROM ${qq(this.User.tableName)};`, { type: this.sequelize.QueryTypes.SELECT @@ -93,8 +116,8 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { it('properly bind parameters on extra retries', async function() { const payload = { username: 'test', - createdAt: '2010-10-10 00:00:00', - updatedAt: '2010-10-10 00:00:00' + createdAt: dialect === 'oracle' ? new Date('2010-10-10 00:00:00') : '2010-10-10 00:00:00', + updatedAt: dialect === 'oracle' ? new Date('2010-10-10 00:00:00') : '2010-10-10 00:00:00' }; const spy = sinon.spy(); @@ -125,7 +148,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { benchmark: true }); - await sequelize.query('select 1;'); + await sequelize.query(`select 1${Support.addDualInSelect()};`); expect(logger.calledOnce).to.be.true; expect(logger.args[0][0]).to.be.match(/Executed \((\d*|default)\): select 1/); expect(typeof logger.args[0][1] === 'number').to.be.true; @@ -134,7 +157,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { it('executes a query with benchmarking option and custom logger', async function() { const logger = sinon.spy(); - await this.sequelize.query('select 1;', { + await this.sequelize.query(`select 1${Support.addDualInSelect()};`, { logging: logger, benchmark: true }); @@ -199,7 +222,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { if (dialect === 'db2') { typeCast = '::VARCHAR'; } - await this.sequelize.query(`select $1${typeCast} as foo, $2${typeCast} as bar`, { bind: ['foo', 'bar'], logging: s=>logSql = s }); + await this.sequelize.query(`select $1${typeCast} as foo, $2${typeCast} as bar${Support.addDualInSelect()}`, { bind: ['foo', 'bar'], logging: s=>logSql = s }); expect(logSql).to.match(/; ("foo", "bar"|{"(\$1|0)":"foo","(\$2|1)":"bar"})/); }); }); @@ -372,7 +395,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { const query = `INSERT INTO ${qq(this.User.tableName)} (username, email_address, ${ qq('createdAt') }, ${qq('updatedAt') }) VALUES ('duplicate', 'duplicate@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10')`; - if (dialect === 'db2') { + if (['db2', 'oracle'].includes(dialect)) { this.query = `INSERT INTO ${qq(this.User.tableName)} ("username", "email_address", ${ qq('createdAt') }, ${qq('updatedAt') }) VALUES ('duplicate', 'duplicate@gmail.com', '2012-01-01 10:10:10', '2012-01-01 10:10:10')`; @@ -386,7 +409,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { } catch (err) { error = err; } - if (dialect === 'db2') { + if (['db2', 'oracle'].includes(dialect)) { expect(error).to.be.instanceOf(DatabaseError); } else { expect(error).to.be.instanceOf(UniqueConstraintError); @@ -403,7 +426,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { )}, ${qq( 'updatedAt' )}) VALUES (123456789, '2012-01-01 10:10:10', '2012-01-01 10:10:10', '2012-01-01 10:10:10')`; - if (dialect === 'db2') { + if (['db2', 'oracle'].includes(dialect)) { this.query = `INSERT INTO ${qq(this.UserVisit.tableName)} ("user_id", "visited_at", ${qq( 'createdAt' )}, ${qq( @@ -414,7 +437,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { } catch (err) { error = err; } - if (dialect === 'db2') { + if (['db2', 'oracle'].includes(dialect)) { expect(error).to.be.instanceOf(DatabaseError); } else { expect(error).to.be.instanceOf(ForeignKeyConstraintError); @@ -545,8 +568,8 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { date.setMilliseconds(0); let sql = 'select ? as number, ? as date,? as string,? as boolean,? as buffer'; - if (dialect === 'db2') { - sql = 'select ? as "number", ? as "date",? as "string",? as "boolean",? as "buffer"'; + if (['db2', 'oracle'].includes(dialect)) { + sql = `select ? as "number", ? as "date",? as "string",? as "boolean",? as "buffer"${ Support.addDualInSelect()}`; } const result = await this.sequelize.query({ query: sql, @@ -561,7 +584,11 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { const res = result[0] || {}; res.date = res.date && new Date(res.date); res.boolean = res.boolean && true; - if (typeof res.buffer === 'string' && res.buffer.startsWith('\\x')) { + + // For Oracle dialect BLOB data doesn't begin with \\x hence we need to convert whole buffer to hex type + if (typeof res.buffer === 'string' && dialect === 'oracle') { + res.buffer = Buffer.from(res.buffer, 'hex'); + } else if (typeof res.buffer === 'string' && res.buffer.startsWith('\\x')) { res.buffer = Buffer.from(res.buffer.substring(2), 'hex'); } expect(res).to.deep.equal({ @@ -581,8 +608,8 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { this.values = [1, 2]; } get query() { - if (dialect === 'db2') { - return 'select ? as "foo", ? as "bar"'; + if (['db2', 'oracle'].includes(dialect)) { + return `select ? as "foo", ? as "bar"${ Support.addDualInSelect()}`; } return 'select ? as foo, ? as bar'; } @@ -592,10 +619,10 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { expect(logSql).to.not.include('?'); }); - const expected = dialect === 'db2' ? [{ FOO: 1, BAR: 2 }] : [{ foo: 1, bar: 2 }]; + const expected = ['db2', 'oracle'].includes(dialect) ? [{ FOO: 1, BAR: 2 }] : [{ foo: 1, bar: 2 }]; it('uses properties `query` and `values` if query is tagged', async function() { let logSql; - const result = await this.sequelize.query({ query: 'select ? as foo, ? as bar', values: [1, 2] }, { type: this.sequelize.QueryTypes.SELECT, logging(s) { logSql = s; } }); + const result = await this.sequelize.query({ query: `select ? as foo, ? as bar${ Support.addDualInSelect()}`, values: [1, 2] }, { type: this.sequelize.QueryTypes.SELECT, logging(s) { logSql = s; } }); expect(result).to.deep.equal(expected); expect(logSql).to.not.include('?'); }); @@ -603,7 +630,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { it('uses properties `query` and `bind` if query is tagged', async function() { const typeCast = dialect === 'postgres' || dialect === 'db2' ? '::int' : ''; let logSql; - const result = await this.sequelize.query({ query: `select $1${typeCast} as foo, $2${typeCast} as bar`, bind: [1, 2] }, { type: this.sequelize.QueryTypes.SELECT, logging(s) { logSql = s; } }); + const result = await this.sequelize.query({ query: `select $1${typeCast} as foo, $2${typeCast} as bar${Support.addDualInSelect()}`, bind: [1, 2] }, { type: this.sequelize.QueryTypes.SELECT, logging(s) { logSql = s; } }); expect(result).to.deep.equal(expected); if (['postgres', 'sqlite'].includes(dialect)) { expect(logSql).to.include('$1'); @@ -617,52 +644,52 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { }); it('dot separated attributes when doing a raw query without nest', async function() { - const tickChar = ['postgres', 'mssql', 'db2'].includes(dialect) ? '"' : '`', - sql = `select 1 as ${Sequelize.Utils.addTicks('foo.bar.baz', tickChar)}`; + const tickChar = ['postgres', 'mssql', 'db2', 'oracle'].includes(dialect) ? '"' : '`', + sql = `select 1 as ${Sequelize.Utils.addTicks('foo.bar.baz', tickChar)}${Support.addDualInSelect()}`; await expect(this.sequelize.query(sql, { raw: true, nest: false }).then(obj => obj[0])).to.eventually.deep.equal([{ 'foo.bar.baz': 1 }]); }); it('destructs dot separated attributes when doing a raw query using nest', async function() { - const tickChar = ['postgres', 'mssql', 'db2'].includes(dialect) ? '"' : '`', - sql = `select 1 as ${Sequelize.Utils.addTicks('foo.bar.baz', tickChar)}`; + const tickChar = ['postgres', 'mssql', 'db2', 'oracle'].includes(dialect) ? '"' : '`', + sql = `select 1 as ${Sequelize.Utils.addTicks('foo.bar.baz', tickChar)}${Support.addDualInSelect()}`; const result = await this.sequelize.query(sql, { raw: true, nest: true }); expect(result).to.deep.equal([{ foo: { bar: { baz: 1 } } }]); }); it('replaces token with the passed array', async function() { - const result = await this.sequelize.query('select ? as foo, ? as bar', { type: this.sequelize.QueryTypes.SELECT, replacements: [1, 2] }); + const result = await this.sequelize.query(`select ? as foo, ? as bar${ Support.addDualInSelect()}`, { type: this.sequelize.QueryTypes.SELECT, replacements: [1, 2] }); expect(result).to.deep.equal(expected); }); it('replaces named parameters with the passed object', async function() { - await expect(this.sequelize.query('select :one as foo, :two as bar', { raw: true, replacements: { one: 1, two: 2 } }).then(obj => obj[0])) + await expect(this.sequelize.query(`select :one as foo, :two as bar${ Support.addDualInSelect()}`, { raw: true, replacements: { one: 1, two: 2 } }).then(obj => obj[0])) .to.eventually.deep.equal(expected); }); it('replaces named parameters with the passed object and ignore those which does not qualify', async function() { - const expected = dialect === 'db2' ? [{ FOO: 1, BAR: 2, BAZ: '00:00' }] : [{ foo: 1, bar: 2, baz: '00:00' }]; - await expect(this.sequelize.query('select :one as foo, :two as bar, \'00:00\' as baz', { raw: true, replacements: { one: 1, two: 2 } }).then(obj => obj[0])) + const expected = ['db2', 'oracle'].includes(dialect) ? [{ FOO: 1, BAR: 2, BAZ: '00:00' }] : [{ foo: 1, bar: 2, baz: '00:00' }]; + await expect(this.sequelize.query(`select :one as foo, :two as bar, '00:00' as baz${ Support.addDualInSelect()}`, { raw: true, replacements: { one: 1, two: 2 } }).then(obj => obj[0])) .to.eventually.deep.equal(expected); }); it('replaces named parameters with the passed object using the same key twice', async function() { - const expected = dialect === 'db2' ? [{ FOO: 1, BAR: 2, BAZ: 1 }] : [{ foo: 1, bar: 2, baz: 1 }]; - await expect(this.sequelize.query('select :one as foo, :two as bar, :one as baz', { raw: true, replacements: { one: 1, two: 2 } }).then(obj => obj[0])) + const expected = ['db2', 'oracle'].includes(dialect) ? [{ FOO: 1, BAR: 2, BAZ: 1 }] : [{ foo: 1, bar: 2, baz: 1 }]; + await expect(this.sequelize.query(`select :one as foo, :two as bar, :one as baz${ Support.addDualInSelect()}`, { raw: true, replacements: { one: 1, two: 2 } }).then(obj => obj[0])) .to.eventually.deep.equal(expected); }); it('replaces named parameters with the passed object having a null property', async function() { - const expected = dialect === 'db2' ? [{ FOO: 1, BAR: null }] : [{ foo: 1, bar: null }]; - await expect(this.sequelize.query('select :one as foo, :two as bar', { raw: true, replacements: { one: 1, two: null } }).then(obj => obj[0])) + const expected = ['db2', 'oracle'].includes(dialect) ? [{ FOO: 1, BAR: null }] : [{ foo: 1, bar: null }]; + await expect(this.sequelize.query(`select :one as foo, :two as bar${ Support.addDualInSelect()}`, { raw: true, replacements: { one: 1, two: null } }).then(obj => obj[0])) .to.eventually.deep.equal(expected); }); it('binds token with the passed array', async function() { const typeCast = dialect === 'postgres' || dialect === 'db2' ? '::int' : ''; let logSql; - const result = await this.sequelize.query(`select $1${typeCast} as foo, $2${typeCast} as bar`, { type: this.sequelize.QueryTypes.SELECT, bind: [1, 2], logging(s) { logSql = s;} }); + const result = await this.sequelize.query(`select $1${typeCast} as foo, $2${typeCast} as bar${Support.addDualInSelect()}`, { type: this.sequelize.QueryTypes.SELECT, bind: [1, 2], logging(s) { logSql = s;} }); expect(result).to.deep.equal(expected); if (['postgres', 'sqlite'].includes(dialect)) { expect(logSql).to.include('$1'); @@ -672,7 +699,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { it('binds named parameters with the passed object', async function() { const typeCast = dialect === 'postgres' || dialect === 'db2' ? '::int' : ''; let logSql; - const result = await this.sequelize.query(`select $one${typeCast} as foo, $two${typeCast} as bar`, { raw: true, bind: { one: 1, two: 2 }, logging(s) { logSql = s; } }); + const result = await this.sequelize.query(`select $one${typeCast} as foo, $two${typeCast} as bar${Support.addDualInSelect()}`, { raw: true, bind: { one: 1, two: 2 }, logging(s) { logSql = s; } }); expect(result[0]).to.deep.equal(expected); if (dialect === 'postgres') { expect(logSql).to.include('$1'); @@ -686,8 +713,9 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { it('binds named parameters with the passed object using the same key twice', async function() { const typeCast = dialect === 'postgres' ? '::int' : ''; let logSql; - const result = await this.sequelize.query(`select $one${typeCast} as foo, $two${typeCast} as bar, $one${typeCast} as baz`, { raw: true, bind: { one: 1, two: 2 }, logging(s) { logSql = s; } }); - expect(result[0]).to.deep.equal([{ foo: 1, bar: 2, baz: 1 }]); + const result = await this.sequelize.query(`select $one${typeCast} as foo, $one${typeCast} as bar, $two${typeCast} as baz${Support.addDualInSelect()}`, { raw: true, bind: { one: 1, two: 2 }, logging(s) { logSql = s; } }); + const expected = dialect !== 'oracle' ? [{ foo: 1, bar: 1, baz: 2 }] : [{ FOO: 1, BAR: 1, BAZ: 2 }]; + expect(result[0]).to.deep.equal(expected); if (dialect === 'postgres') { expect(logSql).to.include('$1'); expect(logSql).to.include('$2'); @@ -697,16 +725,16 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { } it('binds named parameters with the passed object having a null property', async function() { const typeCast = dialect === 'postgres' || dialect === 'db2' ? '::int' : ''; - const result = await this.sequelize.query(`select $one${typeCast} as foo, $two${typeCast} as bar`, { raw: true, bind: { one: 1, two: null } }); - const expected = dialect === 'db2' ? [{ FOO: 1, BAR: null }] : [{ foo: 1, bar: null }]; + const result = await this.sequelize.query(`select $one${typeCast} as foo, $two${typeCast} as bar${Support.addDualInSelect()}`, { raw: true, bind: { one: 1, two: null } }); + const expected = ['db2', 'oracle'].includes(dialect) ? [{ FOO: 1, BAR: null }] : [{ foo: 1, bar: null }]; expect(result[0]).to.deep.equal(expected); }); it('binds named parameters array handles escaped $$', async function() { const typeCast = dialect === 'postgres' || dialect === 'db2' ? '::int' : ''; let logSql; - const result = await this.sequelize.query(`select $1${typeCast} as foo, '$$ / $$1' as bar`, { raw: true, bind: [1], logging(s) { logSql = s;} }); - const expected = dialect === 'db2' ? [{ FOO: 1, BAR: '$ / $1' }] : [{ foo: 1, bar: '$ / $1' }]; + const result = await this.sequelize.query(`select $1${typeCast} as foo, '$$ / $$1' as bar${Support.addDualInSelect()}`, { raw: true, bind: [1], logging(s) { logSql = s;} }); + const expected = ['db2', 'oracle'].includes(dialect) ? [{ FOO: 1, BAR: '$ / $1' }] : [{ foo: 1, bar: '$ / $1' }]; expect(result[0]).to.deep.equal(expected); if (['postgres', 'sqlite', 'db2'].includes(dialect)) { expect(logSql).to.include('$1'); @@ -715,22 +743,23 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { it('binds named parameters object handles escaped $$', async function() { const typeCast = dialect === 'postgres' || dialect === 'db2' ? '::int' : ''; - const result = await this.sequelize.query(`select $one${typeCast} as foo, '$$ / $$one' as bar`, { raw: true, bind: { one: 1 } }); - const expected = dialect === 'db2' ? [{ FOO: 1, BAR: '$ / $one' }] : [{ foo: 1, bar: '$ / $one' }]; + const result = await this.sequelize.query(`select $one${typeCast} as foo, '$$ / $$one' as bar${Support.addDualInSelect()}`, { raw: true, bind: { one: 1 } }); + const expected = ['db2', 'oracle'].includes(dialect) ? [{ FOO: 1, BAR: '$ / $one' }] : [{ foo: 1, bar: '$ / $one' }]; expect(result[0]).to.deep.equal(expected); }); it('escape where has $ on the middle of characters', async function() { const typeCast = dialect === 'postgres' || dialect === 'db2' ? '::int' : ''; - const result = await this.sequelize.query(`select $one${typeCast} as foo$bar`, { raw: true, bind: { one: 1 } }); - const expected = dialect === 'db2' ? [{ FOO$BAR: 1 }] : [{ foo$bar: 1 }]; + const result = await this.sequelize.query(`select $one${typeCast} as foo$bar${Support.addDualInSelect()}`, { raw: true, bind: { one: 1 } }); + const expected = ['db2', 'oracle'].includes(dialect) ? [{ FOO$BAR: 1 }] : [{ foo$bar: 1 }]; expect(result[0]).to.deep.equal(expected); }); - if (['postgres', 'sqlite', 'mssql'].includes(dialect)) { + if (['postgres', 'sqlite', 'mssql', 'oracle'].includes(dialect)) { it('does not improperly escape arrays of strings bound to named parameters', async function() { - const result = await this.sequelize.query('select :stringArray as foo', { raw: true, replacements: { stringArray: ['"string"'] } }); - expect(result[0]).to.deep.equal([{ foo: '"string"' }]); + const result = await this.sequelize.query(`select :stringArray as foo${ Support.addDualInSelect()}`, { raw: true, replacements: { stringArray: ['"string"'] } }); + const expectedData = dialect !== 'oracle' ? { foo: '"string"' } : { FOO: '"string"' }; + expect(result[0]).to.deep.equal([expectedData]); }); } @@ -738,9 +767,11 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { let datetime = dialect === 'sqlite' ? 'date(\'now\')' : 'NOW()'; if (dialect === 'mssql') { datetime = 'GETDATE()'; + } else if (dialect === 'oracle') { + datetime = 'SYSDATE'; } - const [result] = await this.sequelize.query(`SELECT ${datetime} AS t`); + const [result] = await this.sequelize.query(`SELECT ${datetime} AS t${Support.addDualInSelect()}`); expect(moment(result[0].t).isValid()).to.be.true; }); diff --git a/test/integration/sequelize/truncate.test.js b/test/integration/sequelize/truncate.test.js new file mode 100644 index 000000000000..8ae4ff79161b --- /dev/null +++ b/test/integration/sequelize/truncate.test.js @@ -0,0 +1,47 @@ +'use strict'; + +const { Deferrable, DataTypes } = require('sequelize'); +const { expect } = require('chai'); +const { sequelize } = require('../support'); + +describe('Sequelize#truncate', () => { + // These dialects do not support the CASCADE option on TRUNCATE, so it's impossible to clear + // tables that reference each-other. + if (!['mysql', 'mariadb', 'mssql', 'db2', 'oracle'].includes(sequelize.dialect.name)) { + it('supports truncating cyclic associations with { cascade: true }', async () => { + const A = sequelize.define('A', { + BId: { type: DataTypes.INTEGER } + }); + + const B = sequelize.define('B', { + AId: { type: DataTypes.INTEGER } + }); + + // These models both have a foreign key that references the other model. + // Sequelize should be able to create them. + A.belongsTo(B, { foreignKey: { allowNull: true } }); + B.belongsTo(A, { foreignKey: { allowNull: false } }); + + await sequelize.sync(); + + await sequelize.transaction({ deferrable: Deferrable.SET_DEFERRED }, async transaction => { + const a = await A.create({ + BId: null + }, { transaction }); + + const b = await B.create({ + AId: a.id + }, { transaction }); + + a.BId = b.id; + await a.save({ transaction }); + }); + + // drop both tables + await sequelize.truncate({ cascade: true }); + + expect(await A.count()).to.eq(0); + expect(await B.count()).to.eq(0); + }); + } +}); diff --git a/test/integration/timezone.test.js b/test/integration/timezone.test.js index 9c17d7b205c2..b8ab03f88eb0 100644 --- a/test/integration/timezone.test.js +++ b/test/integration/timezone.test.js @@ -29,7 +29,10 @@ if (dialect !== 'sqlite') { let query = `SELECT ${now} as now`; if (dialect === 'db2') { query = `SELECT ${now} as "now"`; + } else if (dialect === 'oracle') { + query = 'SELECT sysdate AS "now" FROM DUAL'; } + const [now1, now2] = await Promise.all([ this.sequelize.query(query, { type: this.sequelize.QueryTypes.SELECT }), this.sequelizeWithTimezone.query(query, { type: this.sequelize.QueryTypes.SELECT }) diff --git a/test/integration/transaction.test.js b/test/integration/transaction.test.js index 9de28f693b8b..5e69356c2773 100644 --- a/test/integration/transaction.test.js +++ b/test/integration/transaction.test.js @@ -88,7 +88,7 @@ if (current.dialect.supports.transactions) { await this.sequelize.transaction(t => { transaction = t; transaction.afterCommit(hook); - return this.sequelize.query('SELECT 1+1', { transaction, type: QueryTypes.SELECT }); + return this.sequelize.query(`SELECT 1+1${ Support.addDualInSelect()}`, { transaction, type: QueryTypes.SELECT }); }); expect(hook).to.have.been.calledOnce; @@ -189,24 +189,24 @@ if (current.dialect.supports.transactions) { it('does not allow queries after commit', async function() { const t = await this.sequelize.transaction(); - await this.sequelize.query('SELECT 1+1', { transaction: t, raw: true }); + await this.sequelize.query(`SELECT 1+1${ Support.addDualInSelect()}`, { transaction: t, raw: true }); await t.commit(); - await expect(this.sequelize.query('SELECT 1+1', { transaction: t, raw: true })).to.be.eventually.rejectedWith( + await expect(this.sequelize.query(`SELECT 1+1${ Support.addDualInSelect()}`, { transaction: t, raw: true })).to.be.eventually.rejectedWith( Error, /commit has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/ - ).and.have.deep.property('sql').that.equal('SELECT 1+1'); + ).and.have.deep.property('sql').that.equal(`SELECT 1+1${ Support.addDualInSelect()}`); }); it('does not allow queries immediately after commit call', async function() { await expect((async () => { const t = await this.sequelize.transaction(); - await this.sequelize.query('SELECT 1+1', { transaction: t, raw: true }); + await this.sequelize.query(`SELECT 1+1${ Support.addDualInSelect()}`, { transaction: t, raw: true }); await Promise.all([ expect(t.commit()).to.eventually.be.fulfilled, - expect(this.sequelize.query('SELECT 1+1', { transaction: t, raw: true })).to.be.eventually.rejectedWith( + expect(this.sequelize.query(`SELECT 1+1${ Support.addDualInSelect()}`, { transaction: t, raw: true })).to.be.eventually.rejectedWith( Error, /commit has been called on this transaction\([^)]+\), you can no longer use it\. \(The rejected query is attached as the 'sql' property of this error\)/ - ).and.have.deep.property('sql').that.equal('SELECT 1+1') + ).and.have.deep.property('sql').that.equal(`SELECT 1+1${ Support.addDualInSelect()}`) ]); })()).to.be.eventually.fulfilled; }); @@ -780,7 +780,7 @@ if (current.dialect.supports.transactions) { } // PostgreSQL is excluded because it detects Serialization Failure on commit instead of acquiring locks on the read rows - if (!['sqlite', 'postgres', 'postgres-native', 'db2'].includes(dialect)) { + if (!['sqlite', 'postgres', 'postgres-native', 'db2', 'oracle'].includes(dialect)) { it('should block updates after reading a row using SERIALIZABLE', async function() { const User = this.sequelize.define('user', { username: Support.Sequelize.STRING @@ -824,29 +824,41 @@ if (current.dialect.supports.transactions) { t2Spy = sinon.spy(); await this.sequelize.sync({ force: true }); - await User.create({ username: 'jan' }); + const { id } = await User.create({ username: 'jan' }); const t1 = await this.sequelize.transaction(); - const t1Jan = await User.findOne({ - where: { - username: 'jan' - }, - lock: t1.LOCK.UPDATE, - transaction: t1 - }); + // SQL constructs 'FOR UPDATE' with 'FETCH'/'ORDER BY' throws error, + // ORA-02014 for Oracle dialect. Hence using findByPk to test + // the lock behaviour. + let t1Jan; + if (dialect === 'oracle') { + t1Jan = await User.findByPk(id, { transaction: t1, lock: t1.LOCK.UPDATE }); + } else { + t1Jan = await User.findOne({ + where: { + username: 'jan' + }, + lock: t1.LOCK.UPDATE, + transaction: t1 + }); + } const t2 = await this.sequelize.transaction({ isolationLevel: Transaction.ISOLATION_LEVELS.READ_COMMITTED }); await Promise.all([(async () => { - await User.findOne({ - where: { - username: 'jan' - }, - lock: t2.LOCK.UPDATE, - transaction: t2 - }); + if (dialect === 'oracle') { + await User.findByPk(id, { transaction: t2, lock: t2.LOCK.UPDATE }); + } else { + await User.findOne({ + where: { + username: 'jan' + }, + lock: t2.LOCK.UPDATE, + transaction: t2 + }); + } t2Spy(); await t2.commit(); @@ -873,7 +885,7 @@ if (current.dialect.supports.transactions) { await this.sequelize.sync({ force: true }); - await Promise.all([ + const [id1, id2] = await Promise.all([ User.create( { username: 'jan' } ), @@ -884,23 +896,45 @@ if (current.dialect.supports.transactions) { const t1 = await this.sequelize.transaction(); - const results = await User.findAll({ - limit: 1, - lock: true, - transaction: t1 - }); + let results; + if (dialect === 'oracle') { + results = await User.findByPk(id1.id, { transaction: t1, lock: true }); + } else { + results = await User.findAll({ + limit: 1, + lock: true, + transaction: t1 + }); + } + + let firstUserId; + if (dialect === 'oracle') { + firstUserId = results.id; + } else { + firstUserId = results[0].id; + } - const firstUserId = results[0].id; const t2 = await this.sequelize.transaction(); - const secondResults = await User.findAll({ - limit: 1, - lock: true, - skipLocked: true, - transaction: t2 - }); + let secondResults; + if (dialect === 'oracle') { + secondResults = await User.findByPk(id2.id, { transaction: t2, lock: true }); + } else { + secondResults = await User.findAll({ + limit: 1, + lock: true, + skipLocked: true, + transaction: t2 + }); + } + let secondUserId; + if (dialect === 'oracle') { + secondUserId = secondResults.id; + } else { + secondUserId = secondResults[0].id; + } - expect(secondResults[0].id).to.not.equal(firstUserId); + expect(secondUserId).to.not.equal(firstUserId); await Promise.all([ t1.commit(), @@ -929,6 +963,13 @@ if (current.dialect.supports.transactions) { if (current.dialect.supports.lockOuterJoinFailure) { + let error; + if (dialect === 'oracle') { + error = 'ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY, etc'; + } else { + error = 'FOR UPDATE cannot be applied to the nullable side of an outer join'; + } + return expect(User.findOne({ where: { username: 'John' @@ -936,7 +977,7 @@ if (current.dialect.supports.transactions) { include: [Task], lock: t1.LOCK.UPDATE, transaction: t1 - })).to.be.rejectedWith('FOR UPDATE cannot be applied to the nullable side of an outer join'); + })).to.be.rejectedWith(error); } return User.findOne({ diff --git a/test/integration/utils.test.js b/test/integration/utils.test.js index 0b65c75f4dbe..ea3e09bbbd4c 100644 --- a/test/integration/utils.test.js +++ b/test/integration/utils.test.js @@ -159,8 +159,7 @@ describe(Support.getTestDialectTeaser('Utils'), () => { } ]); }); - - if (Support.getTestDialect() !== 'mssql') { + if (!['mssql', 'oracle'].includes(Support.getTestDialect())) { it('accepts condition object (with cast)', async function() { const type = Support.getTestDialect() === 'mysql' ? 'unsigned' : 'int'; @@ -188,7 +187,7 @@ describe(Support.getTestDialectTeaser('Utils'), () => { }); } - if (Support.getTestDialect() !== 'mssql' && Support.getTestDialect() !== 'postgres') { + if (!['mssql', 'postgres', 'oracle'].includes(Support.getTestDialect())) { it('accepts condition object (auto casting)', async function() { const [airplane] = await Airplane.findAll({ attributes: [ diff --git a/test/support.js b/test/support.js index fe621ec9a909..70c0530d3d0c 100644 --- a/test/support.js +++ b/test/support.js @@ -4,6 +4,7 @@ const fs = require('fs'); const path = require('path'); const { inspect, isDeepStrictEqual } = require('util'); const _ = require('lodash'); +const assert = require('assert'); const Sequelize = require('sequelize'); const Config = require('./config/config'); @@ -104,7 +105,7 @@ const Support = { createSequelizeInstance(options) { options = options || {}; - options.dialect = this.getTestDialect(); + options.dialect = Support.getTestDialect(); const config = Config[options.dialect]; @@ -126,7 +127,7 @@ const Support = { sequelizeOptions.storage = config.storage; } - return this.getSequelizeInstance(config.database, config.username, config.password, sequelizeOptions); + return Support.getSequelizeInstance(config.database, config.username, config.password, sequelizeOptions); }, getConnectionOptionsWithoutPool() { @@ -173,7 +174,8 @@ const Support = { }, getSupportedDialects() { - return fs.readdirSync(path.join(distDir, 'dialects')) + return fs + .readdirSync(path.join(distDir, 'dialects')) .filter(file => !file.includes('.js') && !file.includes('abstract')); }, @@ -221,7 +223,29 @@ const Support = { }, expectsql(query, assertions) { - const expectations = assertions.query || assertions; + const rawExpectationMap = + 'query' in assertions ? assertions.query : assertions; + const expectations = Object.create(null); + + for (const [key, value] of Object.entries(rawExpectationMap)) { + const acceptedDialects = key.split(' '); + + for (const dialect of acceptedDialects) { + if (dialect === 'default' && acceptedDialects.length > 1) { + throw new Error( + 'The \'default\' expectation cannot be combined with other dialects.' + ); + } + + if (expectations[dialect] !== undefined) { + throw new Error( + `The expectation for ${dialect} was already defined.` + ); + } + + expectations[dialect] = value; + } + } let expectation = expectations[Support.sequelize.dialect.name]; const dialect = Support.sequelize.dialect; @@ -275,6 +299,10 @@ const Support = { .replace(/\( /g, '(') // remove whitespace at start & end .trim(); + }, + + addDualInSelect() { + return this.getTestDialect() === 'oracle' ? ' FROM DUAL' : ''; } }; @@ -287,5 +315,119 @@ if (global.beforeEach) { }); } +function expectPerDialect(method, assertions) { + const expectations = Object.create(null); + + for (const [key, value] of Object.entries(assertions)) { + const acceptedDialects = key.split(' '); + + for (const dialect of acceptedDialects) { + if (dialect === 'default' && acceptedDialects.length > 1) { + throw new Error( + 'The \'default\' expectation cannot be combined with other dialects.' + ); + } + + if (expectations[dialect] !== undefined) { + throw new Error(`The expectation for ${dialect} was already defined.`); + } + + expectations[dialect] = value; + } + } + + let result; + + try { + result = method(); + } catch (error) { + assert(error instanceof Error, 'method threw a non-error'); + + result = error; + } + + let expectation = expectations[Support.sequelize.dialect.name]; + expectation = expectation != null ? expectation : expectations.default; + + if (expectation === undefined) { + throw new Error( + `No expectation was defined for ${Support.sequelize.dialect.name} and the 'default' expectation has not been defined.` + ); + } + + if (expectation instanceof Error) { + assert( + result instanceof Error, + `Expected method to error with "${ + expectation.message + }", but it returned ${inspect(result)}.` + ); + + expect(result.message).to.equal(expectation.message); + } else { + assert( + !(result instanceof Error), + `Did not expect query to error, but it errored with ${ + result instanceof Error ? result.message : '' + }` + ); + + assertMatchesExpectation(result, expectation); + } +} + +function assertMatchesExpectation(result, expectation) { + if (expectation instanceof Expectation) { + expectation.assert(result); + } else { + expect(result).to.deep.equal(expectation); + } +} + +class Expectation { + assert(value) {} +} + +class SqlExpectation extends Expectation { + constructor(sql) { + super(); + this.sql = sql; + } + + assert(value) { + expect(Support.minifySql(value)).to.equal(Support.minifySql(this.sql)); + } +} + +function toMatchSql(sql) { + return new SqlExpectation(sql); +} + +class HasPropertiesExpectation extends Expectation { + constructor(properties) { + super(); + this.properties = properties; + } + + assert(value) { + console.log({ + value, + props: this.properties, + keys: Object.keys(this.properties) + }); + for (const key of Object.keys(this.properties)) { + console.log({ key, value: value[key], expected: this.properties[key] }); + assertMatchesExpectation(value[key], this.properties[key]); + } + } +} + +function toHaveProperties(properties) { + return new HasPropertiesExpectation(properties); +} + Support.sequelize = Support.createSequelizeInstance(); +Support.expectPerDialect = expectPerDialect; +Support.toMatchSql = toMatchSql; +Support.toHaveProperties = toHaveProperties; module.exports = Support; diff --git a/test/types/bulk-create.ts b/test/types/bulk-create.ts new file mode 100644 index 000000000000..cd76fad9eb5e --- /dev/null +++ b/test/types/bulk-create.ts @@ -0,0 +1,60 @@ +import { + Model, + InferAttributes, + CreationOptional, + InferCreationAttributes, +} from 'sequelize'; +import { sequelize } from './connection'; +import type { MakeNullishOptional } from 'sequelize/types/utils'; + +class TestModel extends Model< + InferAttributes, + InferCreationAttributes +> { + declare id: CreationOptional; + declare testString: CreationOptional; + declare testEnum: CreationOptional<'d' | 'e' | 'f' | null>; +} + +type wat = InferCreationAttributes; + +sequelize.transaction(async trx => { + const newItems: Array< + MakeNullishOptional> + > = [ + { + testEnum: 'e', + testString: 'abc', + }, + { + testEnum: null, + testString: undefined, + }, + ]; + + const res1: Array = await TestModel.bulkCreate(newItems, { + benchmark: true, + fields: ['testEnum'], + hooks: true, + logging: true, + returning: true, + transaction: trx, + validate: true, + ignoreDuplicates: true, + }); + + const res2: Array = await TestModel.bulkCreate(newItems, { + benchmark: true, + fields: ['testEnum'], + hooks: true, + logging: true, + returning: false, + transaction: trx, + validate: true, + updateOnDuplicate: ['testEnum', 'testString'], + }); + + const res3: Array = await TestModel.bulkCreate(newItems, { + conflictAttributes: ['testEnum', 'testString'], + }); +}); diff --git a/test/types/hooks.ts b/test/types/hooks.ts index 330addeecd53..4f3dfff92f50 100644 --- a/test/types/hooks.ts +++ b/test/types/hooks.ts @@ -1,5 +1,6 @@ import { expectTypeOf } from "expect-type"; import { FindOptions, Model, QueryOptions, SaveOptions, Sequelize, UpsertOptions, Config, Utils } from "sequelize"; +import { Connection, GetConnectionOptions } from "sequelize/lib/dialects/abstract/connection-manager"; import { ModelHooks } from "sequelize/lib/hooks"; import { AbstractQuery } from "sequelize/lib/query"; import { SemiDeepWritable } from "./type-helpers/deep-writable"; @@ -85,4 +86,29 @@ import { SemiDeepWritable } from "./type-helpers/deep-writable"; Sequelize.beforeConnect('name', config => expectTypeOf(config).toEqualTypeOf>()); Sequelize.beforeConnect(config => expectTypeOf(config).toEqualTypeOf>()); Sequelize.addHook('beforeConnect', (...args) => { expectTypeOf(args).toEqualTypeOf<[Utils.DeepWriteable]>(); }); + Sequelize.beforePoolAcquire('name', (options?: GetConnectionOptions) => { + expectTypeOf(options).toMatchTypeOf(); + }); + + Sequelize.beforePoolAcquire((options?: GetConnectionOptions) => { + expectTypeOf(options).toMatchTypeOf(); + }); + + Sequelize.addHook('beforePoolAcquire', (...args: [GetConnectionOptions | undefined]) => { + expectTypeOf(args).toMatchTypeOf<[GetConnectionOptions | undefined]>(); + }); + + Sequelize.afterPoolAcquire('name', (connection: Connection, options?: GetConnectionOptions) => { + expectTypeOf(connection).toMatchTypeOf(); + expectTypeOf(options).toMatchTypeOf(); + }); + + Sequelize.afterPoolAcquire((connection: Connection, options?: GetConnectionOptions) => { + expectTypeOf(connection).toMatchTypeOf(); + expectTypeOf(options).toMatchTypeOf(); + }); + + Sequelize.addHook('afterPoolAcquire', (...args: [Connection | GetConnectionOptions | undefined]) => { + expectTypeOf(args).toMatchTypeOf<[Connection | GetConnectionOptions | undefined]>(); + }); } diff --git a/test/types/model.ts b/test/types/model.ts index 942c1c25bfb4..a05ff9fe0c1c 100644 --- a/test/types/model.ts +++ b/test/types/model.ts @@ -80,6 +80,30 @@ MyModel.count({ group: 'type' }).then((result) => { expectTypeOf(result[0]).toMatchTypeOf<{ count: number }>(); }); +MyModel.increment('int', { by: 1 }).then(result => { + expectTypeOf(result).toEqualTypeOf<[affectedRows: MyModel[], affectedCount?: number]>(); +}); + +MyModel.increment({ int: 2 }, {}).then(result => { + expectTypeOf(result).toEqualTypeOf<[affectedRows: MyModel[], affectedCount?: number]>(); +}); + +MyModel.increment(['int'], { by: 3 }).then(result => { + expectTypeOf(result).toEqualTypeOf<[affectedRows: MyModel[], affectedCount?: number]>(); +}); + +MyModel.decrement('int', { by: 1 }).then(result => { + expectTypeOf(result).toEqualTypeOf<[affectedRows: MyModel[], affectedCount?: number]>(); +}); + +MyModel.decrement({ int: 2 }, {}).then(result => { + expectTypeOf(result).toEqualTypeOf<[affectedRows: MyModel[], affectedCount?: number]>(); +}); + +MyModel.decrement(['int'], { by: 3 }).then(result => { + expectTypeOf(result).toEqualTypeOf<[affectedRows: MyModel[], affectedCount?: number]>(); +}); + MyModel.build({ int: 10 }, { include: OtherModel }); MyModel.bulkCreate([{ int: 10 }], { include: OtherModel, searchPath: 'public' }); diff --git a/test/types/sequelize.ts b/test/types/sequelize.ts index 702237f492c3..d57a65d80d8c 100644 --- a/test/types/sequelize.ts +++ b/test/types/sequelize.ts @@ -37,6 +37,7 @@ sequelize.and() sequelize.or() sequelize.json('data.id') sequelize.where(sequelize.col("ABS"), Op.is, null); +sequelize.getQueryInterface(); const databaseName = sequelize.getDatabaseName(); diff --git a/test/types/upsert.ts b/test/types/upsert.ts index 9870b53b83b4..53877d8a5546 100644 --- a/test/types/upsert.ts +++ b/test/types/upsert.ts @@ -43,4 +43,11 @@ sequelize.transaction(async trx => { validate: true, conflictFields: ['foo', 'bar'] }); + + const res4: [TestModel, boolean | null] = await TestModel.upsert({}, { + conflictWhere: { + foo: 'abc', + bar: 'def', + }, + }); }) diff --git a/test/unit/dialect-module-configuration.test.js b/test/unit/dialect-module-configuration.test.js index 8758d26cd79b..5d6017a6f031 100644 --- a/test/unit/dialect-module-configuration.test.js +++ b/test/unit/dialect-module-configuration.test.js @@ -33,6 +33,7 @@ describe(Support.getTestDialectTeaser('Sequelize'), () => { case 'mssql': dialectPath = path.join(dialectPath, 'tedious'); break; case 'sqlite': dialectPath = path.join(dialectPath, 'sqlite3'); break; case 'snowflake': dialectPath = path.join(dialectPath, 'snowflake-sdk'); break; + case 'oracle': dialectPath = path.join(dialectPath, 'oracledb'); break; default: throw Error('Unsupported dialect'); } diff --git a/test/unit/dialects/abstract/query-generator.test.js b/test/unit/dialects/abstract/query-generator.test.js index 3ed56dd17ba1..d0d69b000058 100644 --- a/test/unit/dialects/abstract/query-generator.test.js +++ b/test/unit/dialects/abstract/query-generator.test.js @@ -4,7 +4,8 @@ const chai = require('chai'), expect = chai.expect, Op = require('../../../../lib/operators'), Support = require('../../support'), - getAbstractQueryGenerator = Support.getAbstractQueryGenerator; + getAbstractQueryGenerator = Support.getAbstractQueryGenerator, + expectsql = Support.expectsql; const AbstractQueryGenerator = require('sequelize/lib/dialects/abstract/query-generator'); describe('QueryGenerator', () => { @@ -120,10 +121,22 @@ describe('QueryGenerator', () => { .should.be.equal('foo IS NOT NULL'); }); - it('should correctly escape $ in sequelize.fn arguments', function() { + it('should correctly escape a single $ in sequelize.fn arguments', function() { const QG = getAbstractQueryGenerator(this.sequelize); - QG.handleSequelizeMethod(this.sequelize.fn('upper', '$user')) - .should.include('$$user'); + const value = QG.handleSequelizeMethod(this.sequelize.fn('upper', '$user')); + expectsql(value, { + mssql: "upper(N'$$user')", + default: "upper('$$user')" + }); + }); + + it('should correctly escape multiple instances of "$" in sequelize.fn arguments', function() { + const QG = getAbstractQueryGenerator(this.sequelize); + const value = QG.handleSequelizeMethod(this.sequelize.fn('upper', '$user and then another $user and some dollars: $42.69')); + expectsql(value, { + mssql: 'upper(N\'$$user and then another $$user and some dollars: $$42.69\')', + default: 'upper(\'$$user and then another $$user and some dollars: $$42.69\')' + }); }); }); @@ -153,6 +166,7 @@ describe('QueryGenerator', () => { mysql: query => expect(query()).to.equal("json_unquote(json_extract(profile,'$.\\\"id\\\"'))"), mssql: query => expect(query).to.throw(Error), snowflake: query => expect(query).to.throw(Error), + oracle: query => expect(query).to.throw(Error), db2: query => expect(query).to.throw(Error) }); }); @@ -166,6 +180,7 @@ describe('QueryGenerator', () => { mysql: query => expect(query()).to.equal("json_unquote(json_extract(profile,'$.\\\"id\\\"'))"), mssql: query => expect(query).to.throw(Error), snowflake: query => expect(query).to.throw(Error), + oracle: query => expect(query).to.throw(Error), db2: query => expect(query).to.throw(Error) }); }); @@ -179,6 +194,7 @@ describe('QueryGenerator', () => { mysql: query => expect(query()).to.equal("json_unquote(json_extract(profile,'$.\\\"id\\\"'))"), mssql: query => expect(query).to.throw(Error), snowflake: query => expect(query).to.throw(Error), + oracle: query => expect(query).to.throw(Error), db2: query => expect(query).to.throw(Error) }); }); diff --git a/test/unit/dialects/abstract/query.test.js b/test/unit/dialects/abstract/query.test.js index 321c31b4abf9..291e02ccda18 100644 --- a/test/unit/dialects/abstract/query.test.js +++ b/test/unit/dialects/abstract/query.test.js @@ -16,6 +16,9 @@ describe('[ABSTRACT]', () => { id: { primaryKey: true, type: current.Sequelize.STRING(1) + }, + name: { + type: current.Sequelize.TEXT } }); @@ -64,6 +67,7 @@ describe('[ABSTRACT]', () => { 'players.created': new Date('2017-03-06T15:47:30.000Z'), 'players.lastModified': new Date('2017-03-06T15:47:30.000Z'), 'agents.uuid': agentOneUuid, + name: 'vansh', 'agents.id': 'p', 'agents.name': 'One' }, @@ -73,6 +77,7 @@ describe('[ABSTRACT]', () => { 'players.created': new Date('2017-03-06T15:47:30.000Z'), 'players.lastModified': new Date('2017-08-22T11:16:44.000Z'), 'agents.uuid': agentTwoUuid, + name: 'joe', 'agents.id': 'z', 'agents.name': 'Two' } @@ -83,6 +88,7 @@ describe('[ABSTRACT]', () => { expect(result.length).to.be.equal(1); expect(result[0]).to.have.property('id').and.be.equal('a'); + expect(result[0]).to.have.property('name').and.be.ok; expect(result[0].agents).to.be.deep.equal([ { id: 'p', diff --git a/test/unit/dialects/db2/query-generator.test.js b/test/unit/dialects/db2/query-generator.test.js index 3eec7a5dd51f..1c2e9fb1e08d 100644 --- a/test/unit/dialects/db2/query-generator.test.js +++ b/test/unit/dialects/db2/query-generator.test.js @@ -197,7 +197,7 @@ if (dialect === 'db2') { }, { arguments: ['foo', { attributes: [['count(*)', 'count']] }], expectation: 'SELECT count(*) AS "count" FROM "foo";', - context: QueryGenerator + context: { options: { attributeBehavior: 'unsafe-legacy' } } }, { arguments: ['myTable', { order: ['id'] }], expectation: 'SELECT * FROM "myTable" ORDER BY "id";', diff --git a/test/unit/dialects/mariadb/query-generator.test.js b/test/unit/dialects/mariadb/query-generator.test.js index 4622add40a58..909d2d4cae32 100644 --- a/test/unit/dialects/mariadb/query-generator.test.js +++ b/test/unit/dialects/mariadb/query-generator.test.js @@ -278,7 +278,7 @@ if (dialect === 'mariadb') { }, { arguments: ['foo', { attributes: [['count(*)', 'count']] }], expectation: 'SELECT count(*) AS `count` FROM `foo`;', - context: QueryGenerator + context: { options: { attributeBehavior: 'unsafe-legacy' } } }, { arguments: ['myTable', { order: ['id'] }], expectation: 'SELECT * FROM `myTable` ORDER BY `id`;', diff --git a/test/unit/dialects/mssql/query.test.js b/test/unit/dialects/mssql/query.test.js index 4e35145ba4d4..b59e1f7dccce 100644 --- a/test/unit/dialects/mssql/query.test.js +++ b/test/unit/dialects/mssql/query.test.js @@ -66,19 +66,30 @@ if (dialect === 'mssql') { describe('getSQLTypeFromJsType', () => { const TYPES = tedious.TYPES; it('should return correct parameter type', () => { - expect(query.getSQLTypeFromJsType(2147483647, TYPES)).to.eql({ type: TYPES.Int, typeOptions: {} }); - expect(query.getSQLTypeFromJsType(-2147483648, TYPES)).to.eql({ type: TYPES.Int, typeOptions: {} }); + expect(query.getSQLTypeFromJsType(2147483647, TYPES)).to.eql({ type: TYPES.Int, typeOptions: {}, value: 2147483647 }); + expect(query.getSQLTypeFromJsType(-2147483648, TYPES)).to.eql({ type: TYPES.Int, typeOptions: {}, value: -2147483648 }); - expect(query.getSQLTypeFromJsType(2147483648, TYPES)).to.eql({ type: TYPES.BigInt, typeOptions: {} }); - expect(query.getSQLTypeFromJsType(-2147483649, TYPES)).to.eql({ type: TYPES.BigInt, typeOptions: {} }); + expect(query.getSQLTypeFromJsType(2147483648, TYPES)).to.eql({ type: TYPES.BigInt, typeOptions: {}, value: 2147483648 }); + expect(query.getSQLTypeFromJsType(-2147483649, TYPES)).to.eql({ type: TYPES.BigInt, typeOptions: {}, value: -2147483649 }); - expect(query.getSQLTypeFromJsType(Buffer.from('abc'), TYPES)).to.eql({ type: TYPES.VarBinary, typeOptions: {} }); + expect(query.getSQLTypeFromJsType(2147483647n, TYPES)).to.eql({ type: TYPES.Int, typeOptions: {}, value: 2147483647 }); + expect(query.getSQLTypeFromJsType(-2147483648n, TYPES)).to.eql({ type: TYPES.Int, typeOptions: {}, value: -2147483648 }); + + expect(query.getSQLTypeFromJsType(BigInt(Number.MAX_SAFE_INTEGER), TYPES)).to.eql({ type: TYPES.BigInt, typeOptions: {}, value: Number.MAX_SAFE_INTEGER }); + expect(query.getSQLTypeFromJsType(BigInt(Number.MIN_SAFE_INTEGER), TYPES)).to.eql({ type: TYPES.BigInt, typeOptions: {}, value: Number.MIN_SAFE_INTEGER }); + + const overMaxSafe = BigInt(Number.MAX_SAFE_INTEGER) + 1n; + expect(query.getSQLTypeFromJsType(overMaxSafe, TYPES)).to.eql({ type: TYPES.VarChar, typeOptions: {}, value: overMaxSafe.toString() }); + const underMinSafe = BigInt(Number.MIN_SAFE_INTEGER) - 1n; + expect(query.getSQLTypeFromJsType(underMinSafe, TYPES)).to.eql({ type: TYPES.VarChar, typeOptions: {}, value: underMinSafe.toString() }); + + expect(query.getSQLTypeFromJsType(Buffer.from('abc'), TYPES)).to.eql({ type: TYPES.VarBinary, typeOptions: {}, value: Buffer.from('abc') }); }); it('should return parameter type correct scale for float', () => { - expect(query.getSQLTypeFromJsType(1.23, TYPES)).to.eql({ type: TYPES.Numeric, typeOptions: { precision: 30, scale: 2 } }); - expect(query.getSQLTypeFromJsType(0.30000000000000004, TYPES)).to.eql({ type: TYPES.Numeric, typeOptions: { precision: 30, scale: 17 } }); - expect(query.getSQLTypeFromJsType(2.5e-15, TYPES)).to.eql({ type: TYPES.Numeric, typeOptions: { precision: 30, scale: 16 } }); + expect(query.getSQLTypeFromJsType(1.23, TYPES)).to.eql({ type: TYPES.Numeric, typeOptions: { precision: 30, scale: 2 }, value: 1.23 }); + expect(query.getSQLTypeFromJsType(0.30000000000000004, TYPES)).to.eql({ type: TYPES.Numeric, typeOptions: { precision: 30, scale: 17 }, value: 0.30000000000000004 }); + expect(query.getSQLTypeFromJsType(2.5e-15, TYPES)).to.eql({ type: TYPES.Numeric, typeOptions: { precision: 30, scale: 16 }, value: 2.5e-15 }); }); }); diff --git a/test/unit/dialects/mysql/query-generator.test.js b/test/unit/dialects/mysql/query-generator.test.js index 29a1fab1a5ab..41cd997b32db 100644 --- a/test/unit/dialects/mysql/query-generator.test.js +++ b/test/unit/dialects/mysql/query-generator.test.js @@ -235,7 +235,7 @@ if (dialect === 'mysql') { }, { arguments: ['foo', { attributes: [['count(*)', 'count']] }], expectation: 'SELECT count(*) AS `count` FROM `foo`;', - context: QueryGenerator + context: { options: { attributeBehavior: 'unsafe-legacy' } } }, { arguments: ['myTable', { order: ['id'] }], expectation: 'SELECT * FROM `myTable` ORDER BY `id`;', diff --git a/test/unit/dialects/oracle/query-generator.test.js b/test/unit/dialects/oracle/query-generator.test.js new file mode 100644 index 000000000000..de56e22c69bd --- /dev/null +++ b/test/unit/dialects/oracle/query-generator.test.js @@ -0,0 +1,64 @@ + +'use strict'; + +const Support = require('../../support'), + DataTypes = require('sequelize/lib/data-types'), + expectsql = Support.expectsql, + current = Support.sequelize, + sql = current.dialect.queryGenerator, + sinon = require('sinon'); + +if (current.dialect.name === 'oracle') { + describe('createTable', () => { + const FooUser = current.define('user', { + intCol: { + type: DataTypes.INTEGER.UNSIGNED, + allowNull: false, + defaultValue: 0 + } + }, + { + schema: 'foo', + timestamps: false + }); + + describe('[Oracle Specific] QueryGenerator', () => { + it('checks for values >=0', () => { + expectsql(sql.createTableQuery(FooUser.getTableName(), sql.attributesToSQL(FooUser.rawAttributes), { }), { + default: 'BEGIN EXECUTE IMMEDIATE \'CREATE TABLE "foo"."users" ("id" NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY, "intCol" INTEGER DEFAULT 0 NOT NULL check("intCol" >= 0),PRIMARY KEY ("id"))\'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;' }); + }); + }); + }); + + // Alter table for blob tries implicit type conversion if datatype is mentioned in SQL, which leads to failure. + describe('changeColumn', () => { + const Model = current.define('items', { + blobCol: { + type: DataTypes.BLOB + } + }, { timestamps: false }); + + before(function() { + this.stub = sinon.stub(current, 'query').resolvesArg(0); + }); + + beforeEach(function() { + this.stub.resetHistory(); + }); + + after(function() { + this.stub.restore(); + }); + + it('properly generate alter queries for BLOB', () => { + return current.getQueryInterface().changeColumn(Model.getTableName(), 'blobCol', { + type: DataTypes.BLOB, + allowNull: false + }).then(sql => { + expectsql(sql, { + oracle: 'DECLARE CONS_NAME VARCHAR2(200); BEGIN BEGIN EXECUTE IMMEDIATE \'ALTER TABLE "items" MODIFY "blobCol" NOT NULL\'; EXCEPTION WHEN OTHERS THEN IF SQLCODE = -1442 OR SQLCODE = -1451 THEN EXECUTE IMMEDIATE \'ALTER TABLE "items" MODIFY "blobCol" \'; ELSE RAISE; END IF; END; END;' + }); + }); + }); + }); +} diff --git a/test/unit/dialects/postgres/query-generator.test.js b/test/unit/dialects/postgres/query-generator.test.js index b907bdb6bf10..d3c6ed1a19fe 100644 --- a/test/unit/dialects/postgres/query-generator.test.js +++ b/test/unit/dialects/postgres/query-generator.test.js @@ -11,6 +11,10 @@ const chai = require('chai'), current = Support.sequelize, _ = require('lodash'); +const customSequelize = Support.createSequelizeInstance({ + schema: 'custom' +}); + if (dialect.startsWith('postgres')) { describe('[POSTGRES Specific] QueryGenerator', () => { const suites = { @@ -302,7 +306,7 @@ if (dialect.startsWith('postgres')) { col_1: "ENUM('value 1', 'value 2') NOT NULL", col_2: "ENUM('value 3', 'value 4') NOT NULL" }], - expectation: 'ALTER TABLE "myTable" ALTER COLUMN "col_1" SET NOT NULL;ALTER TABLE "myTable" ALTER COLUMN "col_1" DROP DEFAULT;CREATE TYPE "public"."enum_myTable_col_1" AS ENUM(\'value 1\', \'value 2\');ALTER TABLE "myTable" ALTER COLUMN "col_1" TYPE "public"."enum_myTable_col_1" USING ("col_1"::"public"."enum_myTable_col_1");ALTER TABLE "myTable" ALTER COLUMN "col_2" SET NOT NULL;ALTER TABLE "myTable" ALTER COLUMN "col_2" DROP DEFAULT;CREATE TYPE "public"."enum_myTable_col_2" AS ENUM(\'value 3\', \'value 4\');ALTER TABLE "myTable" ALTER COLUMN "col_2" TYPE "public"."enum_myTable_col_2" USING ("col_2"::"public"."enum_myTable_col_2");' + expectation: 'ALTER TABLE "myTable" ALTER COLUMN "col_1" SET NOT NULL;ALTER TABLE "myTable" ALTER COLUMN "col_1" DROP DEFAULT;DO \'BEGIN CREATE TYPE "public"."enum_myTable_col_1" AS ENUM(\'\'value 1\'\', \'\'value 2\'\'); EXCEPTION WHEN duplicate_object THEN null; END\';ALTER TABLE "myTable" ALTER COLUMN "col_1" TYPE "public"."enum_myTable_col_1" USING ("col_1"::"public"."enum_myTable_col_1");ALTER TABLE "myTable" ALTER COLUMN "col_2" SET NOT NULL;ALTER TABLE "myTable" ALTER COLUMN "col_2" DROP DEFAULT;DO \'BEGIN CREATE TYPE "public"."enum_myTable_col_2" AS ENUM(\'\'value 3\'\', \'\'value 4\'\'); EXCEPTION WHEN duplicate_object THEN null; END\';ALTER TABLE "myTable" ALTER COLUMN "col_2" TYPE "public"."enum_myTable_col_2" USING ("col_2"::"public"."enum_myTable_col_2");' } ], @@ -327,7 +331,8 @@ if (dialect.startsWith('postgres')) { expectation: 'SELECT * FROM "myTable" WHERE "myTable"."id" = 2;' }, { arguments: ['foo', { attributes: [['count(*)', 'count']] }], - expectation: 'SELECT count(*) AS "count" FROM "foo";' + expectation: 'SELECT count(*) AS "count" FROM "foo";', + context: { options: { attributeBehavior: 'unsafe-legacy' } } }, { arguments: ['myTable', { order: ['id'] }], expectation: 'SELECT * FROM "myTable" ORDER BY "id";', @@ -522,7 +527,7 @@ if (dialect.startsWith('postgres')) { }, { arguments: ['foo', { attributes: [['count(*)', 'count']] }], expectation: 'SELECT count(*) AS count FROM foo;', - context: { options: { quoteIdentifiers: false } } + context: { options: { quoteIdentifiers: false, attributeBehavior: 'unsafe-legacy' } } }, { arguments: ['myTable', { order: ['id DESC'] }], expectation: 'SELECT * FROM myTable ORDER BY id DESC;', @@ -1201,49 +1206,102 @@ if (dialect.startsWith('postgres')) { } ], + getForeignKeyReferencesQuery: [ + { + arguments: ['myTable', 'myDatabase'], + expectation: 'SELECT ' + + 'DISTINCT tc.constraint_name as constraint_name, ' + + 'tc.constraint_schema as constraint_schema, ' + + 'tc.constraint_catalog as constraint_catalog, ' + + 'tc.table_name as table_name,' + + 'tc.table_schema as table_schema,' + + 'tc.table_catalog as table_catalog,' + + 'tc.initially_deferred as initially_deferred,' + + 'tc.is_deferrable as is_deferrable,' + + 'kcu.column_name as column_name,' + + 'ccu.table_schema AS referenced_table_schema,' + + 'ccu.table_catalog AS referenced_table_catalog,' + + 'ccu.table_name AS referenced_table_name,' + + 'ccu.column_name AS referenced_column_name ' + + 'FROM information_schema.table_constraints AS tc ' + + 'JOIN information_schema.key_column_usage AS kcu ' + + 'ON tc.constraint_name = kcu.constraint_name ' + + 'JOIN information_schema.constraint_column_usage AS ccu ' + + 'ON ccu.constraint_name = tc.constraint_name ' + + 'WHERE constraint_type = \'FOREIGN KEY\' AND tc.table_name = \'myTable\' AND tc.table_catalog = \'myDatabase\'' + }, + { + arguments: ['myTable', 'myDatabase', 'mySchema'], + expectation: 'SELECT ' + + 'DISTINCT tc.constraint_name as constraint_name, ' + + 'tc.constraint_schema as constraint_schema, ' + + 'tc.constraint_catalog as constraint_catalog, ' + + 'tc.table_name as table_name,' + + 'tc.table_schema as table_schema,' + + 'tc.table_catalog as table_catalog,' + + 'tc.initially_deferred as initially_deferred,' + + 'tc.is_deferrable as is_deferrable,' + + 'kcu.column_name as column_name,' + + 'ccu.table_schema AS referenced_table_schema,' + + 'ccu.table_catalog AS referenced_table_catalog,' + + 'ccu.table_name AS referenced_table_name,' + + 'ccu.column_name AS referenced_column_name ' + + 'FROM information_schema.table_constraints AS tc ' + + 'JOIN information_schema.key_column_usage AS kcu ' + + 'ON tc.constraint_name = kcu.constraint_name ' + + 'JOIN information_schema.constraint_column_usage AS ccu ' + + 'ON ccu.constraint_name = tc.constraint_name ' + + 'WHERE constraint_type = \'FOREIGN KEY\' AND tc.table_name = \'myTable\' AND tc.table_catalog = \'myDatabase\' AND tc.table_schema = \'mySchema\'' + } + ], + getForeignKeyReferenceQuery: [ { arguments: ['myTable', 'myColumn'], expectation: 'SELECT ' + - 'DISTINCT tc.constraint_name as constraint_name, ' + - 'tc.constraint_schema as constraint_schema, ' + - 'tc.constraint_catalog as constraint_catalog, ' + - 'tc.table_name as table_name,' + - 'tc.table_schema as table_schema,' + - 'tc.table_catalog as table_catalog,' + - 'kcu.column_name as column_name,' + - 'ccu.table_schema AS referenced_table_schema,' + - 'ccu.table_catalog AS referenced_table_catalog,' + - 'ccu.table_name AS referenced_table_name,' + - 'ccu.column_name AS referenced_column_name ' + + 'DISTINCT tc.constraint_name as constraint_name, ' + + 'tc.constraint_schema as constraint_schema, ' + + 'tc.constraint_catalog as constraint_catalog, ' + + 'tc.table_name as table_name,' + + 'tc.table_schema as table_schema,' + + 'tc.table_catalog as table_catalog,' + + 'tc.initially_deferred as initially_deferred,' + + 'tc.is_deferrable as is_deferrable,' + + 'kcu.column_name as column_name,' + + 'ccu.table_schema AS referenced_table_schema,' + + 'ccu.table_catalog AS referenced_table_catalog,' + + 'ccu.table_name AS referenced_table_name,' + + 'ccu.column_name AS referenced_column_name ' + 'FROM information_schema.table_constraints AS tc ' + - 'JOIN information_schema.key_column_usage AS kcu ' + - 'ON tc.constraint_name = kcu.constraint_name ' + - 'JOIN information_schema.constraint_column_usage AS ccu ' + - 'ON ccu.constraint_name = tc.constraint_name ' + + 'JOIN information_schema.key_column_usage AS kcu ' + + 'ON tc.constraint_name = kcu.constraint_name ' + + 'JOIN information_schema.constraint_column_usage AS ccu ' + + 'ON ccu.constraint_name = tc.constraint_name ' + 'WHERE constraint_type = \'FOREIGN KEY\' AND tc.table_name=\'myTable\' AND kcu.column_name = \'myColumn\'' }, { arguments: [{ schema: 'mySchema', tableName: 'myTable' }, 'myColumn'], expectation: 'SELECT ' + - 'DISTINCT tc.constraint_name as constraint_name, ' + - 'tc.constraint_schema as constraint_schema, ' + - 'tc.constraint_catalog as constraint_catalog, ' + - 'tc.table_name as table_name,' + - 'tc.table_schema as table_schema,' + - 'tc.table_catalog as table_catalog,' + - 'kcu.column_name as column_name,' + - 'ccu.table_schema AS referenced_table_schema,' + - 'ccu.table_catalog AS referenced_table_catalog,' + - 'ccu.table_name AS referenced_table_name,' + - 'ccu.column_name AS referenced_column_name ' + + 'DISTINCT tc.constraint_name as constraint_name, ' + + 'tc.constraint_schema as constraint_schema, ' + + 'tc.constraint_catalog as constraint_catalog, ' + + 'tc.table_name as table_name,' + + 'tc.table_schema as table_schema,' + + 'tc.table_catalog as table_catalog,' + + 'tc.initially_deferred as initially_deferred,' + + 'tc.is_deferrable as is_deferrable,' + + 'kcu.column_name as column_name,' + + 'ccu.table_schema AS referenced_table_schema,' + + 'ccu.table_catalog AS referenced_table_catalog,' + + 'ccu.table_name AS referenced_table_name,' + + 'ccu.column_name AS referenced_column_name ' + 'FROM information_schema.table_constraints AS tc ' + - 'JOIN information_schema.key_column_usage AS kcu ' + - 'ON tc.constraint_name = kcu.constraint_name ' + - 'JOIN information_schema.constraint_column_usage AS ccu ' + - 'ON ccu.constraint_name = tc.constraint_name ' + + 'JOIN information_schema.key_column_usage AS kcu ' + + 'ON tc.constraint_name = kcu.constraint_name ' + + 'JOIN information_schema.constraint_column_usage AS ccu ' + + 'ON ccu.constraint_name = tc.constraint_name ' + 'WHERE constraint_type = \'FOREIGN KEY\' AND tc.table_name=\'myTable\' AND kcu.column_name = \'myColumn\'' + - ' AND tc.table_schema = \'mySchema\'' + ' AND tc.table_schema = \'mySchema\'' } ] }; @@ -1315,5 +1373,40 @@ if (dialect.startsWith('postgres')) { }); }); }); + + describe('With custom schema in Sequelize options', () => { + beforeEach(function() { + this.queryGenerator = new QueryGenerator({ + sequelize: customSequelize, + _dialect: customSequelize.dialect + }); + }); + + const customSchemaSuites = { + showTablesQuery: [ + { + title: 'showTablesQuery defaults to the schema set in Sequelize options', + arguments: [], + expectation: 'SELECT table_name FROM information_schema.tables WHERE table_schema = \'custom\' AND table_type LIKE \'%TABLE\' AND table_name != \'spatial_ref_sys\';' + } + ], + describeTableQuery: [ + { + title: 'describeTableQuery defaults to the schema set in Sequelize options', + arguments: ['myTable', null], + expectation: 'SELECT pk.constraint_type as "Constraint",c.column_name as "Field", c.column_default as "Default",c.is_nullable as "Null", (CASE WHEN c.udt_name = \'hstore\' THEN c.udt_name ELSE c.data_type END) || (CASE WHEN c.character_maximum_length IS NOT NULL THEN \'(\' || c.character_maximum_length || \')\' ELSE \'\' END) as "Type", (SELECT array_agg(e.enumlabel) FROM pg_catalog.pg_type t JOIN pg_catalog.pg_enum e ON t.oid=e.enumtypid WHERE t.typname=c.udt_name) AS "special", (SELECT pgd.description FROM pg_catalog.pg_statio_all_tables AS st INNER JOIN pg_catalog.pg_description pgd on (pgd.objoid=st.relid) WHERE c.ordinal_position=pgd.objsubid AND c.table_name=st.relname) AS "Comment" FROM information_schema.columns c LEFT JOIN (SELECT tc.table_schema, tc.table_name, cu.column_name, tc.constraint_type FROM information_schema.TABLE_CONSTRAINTS tc JOIN information_schema.KEY_COLUMN_USAGE cu ON tc.table_schema=cu.table_schema and tc.table_name=cu.table_name and tc.constraint_name=cu.constraint_name and tc.constraint_type=\'PRIMARY KEY\') pk ON pk.table_schema=c.table_schema AND pk.table_name=c.table_name AND pk.column_name=c.column_name WHERE c.table_name = \'myTable\' AND c.table_schema = \'custom\'' + } + ] + }; + + _.each(customSchemaSuites, (customSchemaTests, customSchemaSuiteTitle) => { + for (const customSchemaTest of customSchemaTests) { + it(customSchemaTest.title, function() { + const convertedText = customSchemaTest.arguments ? this.queryGenerator[customSchemaSuiteTitle](...customSchemaTest.arguments) : this.queryGenerator[customSchemaSuiteTitle](); + expect(convertedText).to.equal(customSchemaTest.expectation); + }); + } + }); + }); }); } diff --git a/test/unit/dialects/snowflake/query-generator.test.js b/test/unit/dialects/snowflake/query-generator.test.js index 18abb64a6132..1104d55512dc 100644 --- a/test/unit/dialects/snowflake/query-generator.test.js +++ b/test/unit/dialects/snowflake/query-generator.test.js @@ -345,7 +345,7 @@ if (dialect === 'snowflake') { arguments: ['myTable'], expectation: 'DROP TABLE IF EXISTS "myTable";' }, - + // Variants when quoteIdentifiers is false { arguments: ['myTable'], @@ -354,6 +354,17 @@ if (dialect === 'snowflake') { } ], + tableExistsQuery: [ + { + arguments: ['myTable'], + expectation: 'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = \'BASE TABLE\' AND TABLE_SCHEMA = CURRENT_SCHEMA() AND TABLE_NAME = \'myTable\';' + }, + { + arguments: [{ tableName: 'myTable', schema: 'mySchema' }], + expectation: 'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = \'BASE TABLE\' AND TABLE_SCHEMA = \'mySchema\' AND TABLE_NAME = \'myTable\';' + } + ], + selectQuery: [ { arguments: ['myTable'], @@ -382,7 +393,7 @@ if (dialect === 'snowflake') { }, { arguments: ['foo', { attributes: [['count(*)', 'count']] }], expectation: 'SELECT count(*) AS "count" FROM "foo";', - context: QueryGenerator + context: { options: { attributeBehavior: 'unsafe-legacy' } } }, { arguments: ['myTable', { order: ['id'] }], expectation: 'SELECT * FROM "myTable" ORDER BY "id";', @@ -658,7 +669,7 @@ if (dialect === 'snowflake') { }, { arguments: ['foo', { attributes: [['count(*)', 'count']] }], expectation: 'SELECT count(*) AS count FROM foo;', - context: { options: { quoteIdentifiers: false } } + context: { options: { quoteIdentifiers: false, attributeBehavior: 'unsafe-legacy' } } }, { arguments: ['myTable', { order: ['id'] }], expectation: 'SELECT * FROM myTable ORDER BY id;', diff --git a/test/unit/dialects/sqlite/query-generator.test.js b/test/unit/dialects/sqlite/query-generator.test.js index 3ef8d5305d29..9719319721db 100644 --- a/test/unit/dialects/sqlite/query-generator.test.js +++ b/test/unit/dialects/sqlite/query-generator.test.js @@ -187,7 +187,7 @@ if (dialect === 'sqlite') { }, { arguments: ['foo', { attributes: [['count(*)', 'count']] }], expectation: 'SELECT count(*) AS `count` FROM `foo`;', - context: QueryGenerator + context: { options: { attributeBehavior: 'unsafe-legacy' } } }, { arguments: ['myTable', { order: ['id'] }], expectation: 'SELECT * FROM `myTable` ORDER BY `id`;', diff --git a/test/unit/esm-named-exports.test.js b/test/unit/esm-named-exports.test.js index 7afcd627740d..6d23808363aa 100644 --- a/test/unit/esm-named-exports.test.js +++ b/test/unit/esm-named-exports.test.js @@ -46,6 +46,7 @@ describe('ESM module', () => { 'mariadb', 'sqlite', 'snowflake', + 'oracle', 'db2', 'mssql', '_setupHooks', @@ -90,6 +91,8 @@ describe('ESM module', () => { 'afterAssociate', 'beforeConnect', 'afterConnect', + 'beforePoolAcquire', + 'afterPoolAcquire', 'beforeDisconnect', 'afterDisconnect', 'beforeSync', diff --git a/test/unit/model/bulk-create.test.js b/test/unit/model/bulk-create.test.js index e7cfa83b0370..a19d3bbffd8a 100644 --- a/test/unit/model/bulk-create.test.js +++ b/test/unit/model/bulk-create.test.js @@ -15,6 +15,11 @@ describe(Support.getTestDialectTeaser('Model'), () => { type: DataTypes.INTEGER(11).UNSIGNED, allowNull: false, field: 'account_id' + }, + purchaseCount: { + type: DataTypes.INTEGER(11).UNSIGNED, + allowNull: false, + underscored: true } }, { timestamps: false }); @@ -32,13 +37,28 @@ describe(Support.getTestDialectTeaser('Model'), () => { describe('validations', () => { it('should not fail for renamed fields', async function() { await this.Model.bulkCreate([ - { accountId: 42 } + { accountId: 42, purchaseCount: 4 } ], { validate: true }); expect(this.stub.getCall(0).args[1]).to.deep.equal([ - { account_id: 42, id: null } + { account_id: 42, purchaseCount: 4, id: null } ]); }); + + if (current.dialect.supports.inserts.updateOnDuplicate) { + it('should map conflictAttributes to column names', async function() { + // Note that the model also has an id key as its primary key. + await this.Model.bulkCreate([{ accountId: 42, purchaseCount: 3 }], { + conflictAttributes: ['accountId'], + updateOnDuplicate: ['purchaseCount'] + }); + + expect( + // Not worth checking that the reference of the array matches - just the contents. + this.stub.getCall(0).args[2].upsertKeys + ).to.deep.equal(['account_id']); + }); + } }); }); }); diff --git a/test/unit/model/update.test.js b/test/unit/model/update.test.js index f11c554cf057..287a69353fcb 100644 --- a/test/unit/model/update.test.js +++ b/test/unit/model/update.test.js @@ -49,4 +49,51 @@ describe(Support.getTestDialectTeaser('Model'), () => { await expect(this.User.update(this.updates, { where: new Where() })).to.be.rejected; }); }); + + describe('Update with multiple models to the same table', () => { + before(function() { + this.Model1 = current.define('Model1', { + value: DataTypes.INTEGER, + name: DataTypes.STRING, + isModel2: DataTypes.BOOLEAN, + model1ExclusiveData: DataTypes.STRING + }, { + tableName: 'model_table' + }); + + this.Model2 = current.define('Model2', { + value: DataTypes.INTEGER, + name: DataTypes.STRING + }, { + tableName: 'model_table' + }); + }); + + beforeEach(function() { + this.stubQuery = sinon.stub(current, 'query').resolves([]); + }); + + afterEach(function() { + this.stubQuery.restore(); + }); + + it('updates model1 using model1 model', async function() { + await this.Model1.update({ + name: 'other name', + model1ExclusiveData: 'only I can update this field' + }, { + where: { value: 1 } + }); + expect(this.stubQuery.lastCall.lastArg.model).to.eq(this.Model1); + }); + + it('updates model2 using model2 model', async function() { + await this.Model2.update({ + name: 'other name' + }, { + where: { value: 2 } + }); + expect(this.stubQuery.lastCall.lastArg.model).to.eq(this.Model2); + }); + }); }); diff --git a/test/unit/query-interface/bulk-insert.test.js b/test/unit/query-interface/bulk-insert.test.js index 6ab4aa7dc405..b9a77b98df28 100644 --- a/test/unit/query-interface/bulk-insert.test.js +++ b/test/unit/query-interface/bulk-insert.test.js @@ -1,6 +1,7 @@ const { DataTypes } = require('sequelize'); const sinon = require('sinon'); const { expectsql, sequelize } = require('../../support'); +const dialect = require('../support').getTestDialect(); const { stubQueryRun } = require('./stub-query-run'); describe('QueryInterface#bulkInsert', () => { @@ -13,7 +14,8 @@ describe('QueryInterface#bulkInsert', () => { }); // you'll find more replacement tests in query-generator tests - it('does not parse replacements outside of raw sql', async () => { + // The Oracle dialect doesn't support replacements for bulkInsert + (dialect !== 'oracle' ? it : it.skip)('does not parse replacements outside of raw sql', async () => { const getSql = stubQueryRun(); await sequelize.getQueryInterface().bulkInsert(User.tableName, [{ diff --git a/test/unit/query-interface/raw-select.test.js b/test/unit/query-interface/raw-select.test.js index 8404ef27bf85..3ec37ec1cb4e 100644 --- a/test/unit/query-interface/raw-select.test.js +++ b/test/unit/query-interface/raw-select.test.js @@ -29,6 +29,7 @@ describe('QueryInterface#rawSelect', () => { expectsql(getSql(), { default: 'SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = \'some :data\';', + oracle: 'SELECT "id" FROM "Users" "User" WHERE "User"."username" = \'some :data\';', mssql: 'SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = N\'some :data\';' }); }); diff --git a/test/unit/query-interface/select.test.js b/test/unit/query-interface/select.test.js index 4e04109a3cf9..d3968c9bc210 100644 --- a/test/unit/query-interface/select.test.js +++ b/test/unit/query-interface/select.test.js @@ -29,6 +29,7 @@ describe('QueryInterface#select', () => { expectsql(getSql(), { default: 'SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = \'some :data\';', + oracle: 'SELECT "id" FROM "Users" "User" WHERE "User"."username" = \'some :data\';', mssql: 'SELECT [id] FROM [Users] AS [User] WHERE [User].[username] = N\'some :data\';' }); }); diff --git a/test/unit/sql/add-column.test.js b/test/unit/sql/add-column.test.js index a13f4d7f077d..0e45cde19856 100644 --- a/test/unit/sql/add-column.test.js +++ b/test/unit/sql/add-column.test.js @@ -1,36 +1,40 @@ 'use strict'; -const Support = require('../support'), - DataTypes = require('sequelize/lib/data-types'), - expectsql = Support.expectsql, - current = Support.sequelize, - sql = current.dialect.queryGenerator; +const Support = require('../support'); +const DataTypes = require('sequelize/lib/data-types'); +const expectsql = Support.expectsql; +const current = Support.sequelize; +const sql = current.dialect.queryGenerator; -if (['mysql', 'mariadb'].includes(current.dialect.name)) { - describe(Support.getTestDialectTeaser('SQL'), () => { - describe('addColumn', () => { +const customSequelize = Support.createSequelizeInstance({ + schema: 'custom' +}); +const customSql = customSequelize.dialect.queryGenerator; - const Model = current.define('users', { - id: { - type: DataTypes.INTEGER, - primaryKey: true, - autoIncrement: true - } - }, { timestamps: false }); +describe(Support.getTestDialectTeaser('SQL'), () => { + describe('addColumn', () => { + const User = current.define('User', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + } + }, { timestamps: false }); + if (['mysql', 'mariadb'].includes(current.dialect.name)) { it('properly generate alter queries', () => { - return expectsql(sql.addColumnQuery(Model.getTableName(), 'level_id', current.normalizeAttribute({ + return expectsql(sql.addColumnQuery(User.getTableName(), 'level_id', current.normalizeAttribute({ type: DataTypes.FLOAT, allowNull: false })), { - mariadb: 'ALTER TABLE `users` ADD `level_id` FLOAT NOT NULL;', - mysql: 'ALTER TABLE `users` ADD `level_id` FLOAT NOT NULL;' + mariadb: 'ALTER TABLE `Users` ADD `level_id` FLOAT NOT NULL;', + mysql: 'ALTER TABLE `Users` ADD `level_id` FLOAT NOT NULL;' }); }); it('properly generate alter queries for foreign keys', () => { - return expectsql(sql.addColumnQuery(Model.getTableName(), 'level_id', current.normalizeAttribute({ + return expectsql(sql.addColumnQuery(User.getTableName(), 'level_id', current.normalizeAttribute({ type: DataTypes.INTEGER, references: { model: 'level', @@ -39,30 +43,80 @@ if (['mysql', 'mariadb'].includes(current.dialect.name)) { onUpdate: 'cascade', onDelete: 'cascade' })), { - mariadb: 'ALTER TABLE `users` ADD `level_id` INTEGER, ADD CONSTRAINT `users_level_id_foreign_idx` FOREIGN KEY (`level_id`) REFERENCES `level` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;', - mysql: 'ALTER TABLE `users` ADD `level_id` INTEGER, ADD CONSTRAINT `users_level_id_foreign_idx` FOREIGN KEY (`level_id`) REFERENCES `level` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;' + mariadb: 'ALTER TABLE `Users` ADD `level_id` INTEGER, ADD CONSTRAINT `Users_level_id_foreign_idx` FOREIGN KEY (`level_id`) REFERENCES `level` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;', + mysql: 'ALTER TABLE `Users` ADD `level_id` INTEGER, ADD CONSTRAINT `Users_level_id_foreign_idx` FOREIGN KEY (`level_id`) REFERENCES `level` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;' }); }); it('properly generate alter queries with FIRST', () => { - return expectsql(sql.addColumnQuery(Model.getTableName(), 'test_added_col_first', current.normalizeAttribute({ + return expectsql(sql.addColumnQuery(User.getTableName(), 'test_added_col_first', current.normalizeAttribute({ type: DataTypes.STRING, first: true })), { - mariadb: 'ALTER TABLE `users` ADD `test_added_col_first` VARCHAR(255) FIRST;', - mysql: 'ALTER TABLE `users` ADD `test_added_col_first` VARCHAR(255) FIRST;' + mariadb: 'ALTER TABLE `Users` ADD `test_added_col_first` VARCHAR(255) FIRST;', + mysql: 'ALTER TABLE `Users` ADD `test_added_col_first` VARCHAR(255) FIRST;' }); }); it('properly generates alter queries with column level comment', () => { - return expectsql(sql.addColumnQuery(Model.getTableName(), 'column_with_comment', current.normalizeAttribute({ + return expectsql(sql.addColumnQuery(User.getTableName(), 'column_with_comment', current.normalizeAttribute({ type: DataTypes.STRING, comment: 'This is a comment' })), { - mariadb: 'ALTER TABLE `users` ADD `column_with_comment` VARCHAR(255) COMMENT \'This is a comment\';', - mysql: 'ALTER TABLE `users` ADD `column_with_comment` VARCHAR(255) COMMENT \'This is a comment\';' + mariadb: 'ALTER TABLE `Users` ADD `column_with_comment` VARCHAR(255) COMMENT \'This is a comment\';', + mysql: 'ALTER TABLE `Users` ADD `column_with_comment` VARCHAR(255) COMMENT \'This is a comment\';' }); }); + } + + it('DEFAULT VALUE FOR BOOLEAN', () => { + return expectsql(sql.addColumnQuery(User.getTableName(), 'bool_col', current.normalizeAttribute({ + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: true + })), { + oracle: 'ALTER TABLE "Users" ADD "bool_col" CHAR(1) DEFAULT 1 NOT NULL CHECK ("bool_col" IN(\'1\', \'0\'))', + mysql: 'ALTER TABLE `Users` ADD `bool_col` TINYINT(1) NOT NULL DEFAULT true;', + mariadb: 'ALTER TABLE `Users` ADD `bool_col` TINYINT(1) NOT NULL DEFAULT true;', + mssql: 'ALTER TABLE [Users] ADD [bool_col] BIT NOT NULL DEFAULT 1;', + postgres: 'ALTER TABLE "public"."Users" ADD COLUMN "bool_col" BOOLEAN NOT NULL DEFAULT true;', + db2: 'ALTER TABLE "Users" ADD "bool_col" BOOLEAN NOT NULL DEFAULT true;', + snowflake: 'ALTER TABLE "Users" ADD "bool_col" BOOLEAN NOT NULL DEFAULT true;', + sqlite: 'ALTER TABLE `Users` ADD `bool_col` TINYINT(1) NOT NULL DEFAULT 1;' + }); + }); + + it('DEFAULT VALUE FOR ENUM', () => { + return expectsql(sql.addColumnQuery(User.getTableName(), 'enum_col', current.normalizeAttribute({ + type: DataTypes.ENUM('happy', 'sad'), + allowNull: false, + defaultValue: 'happy' + })), { + oracle: 'ALTER TABLE "Users" ADD "enum_col" VARCHAR2(512) DEFAULT \'happy\' NOT NULL CHECK ("enum_col" IN(\'happy\', \'sad\'))', + mysql: 'ALTER TABLE `Users` ADD `enum_col` ENUM(\'happy\', \'sad\') NOT NULL DEFAULT \'happy\';', + mariadb: 'ALTER TABLE `Users` ADD `enum_col` ENUM(\'happy\', \'sad\') NOT NULL DEFAULT \'happy\';', + mssql: 'ALTER TABLE [Users] ADD [enum_col] VARCHAR(255) CHECK ([enum_col] IN(N\'happy\', N\'sad\'));', + postgres: 'DO \'BEGIN CREATE TYPE "public"."enum_Users_enum_col" AS ENUM(\'\'happy\'\', \'\'sad\'\'); EXCEPTION WHEN duplicate_object THEN null; END\';ALTER TABLE "public"."Users" ADD COLUMN "enum_col" "public"."enum_Users_enum_col" NOT NULL DEFAULT \'happy\';', + db2: 'ALTER TABLE "Users" ADD "enum_col" VARCHAR(255) CHECK ("enum_col" IN(\'happy\', \'sad\')) NOT NULL DEFAULT \'happy\';', + snowflake: 'ALTER TABLE "Users" ADD "enum_col" ENUM NOT NULL DEFAULT \'happy\';', + sqlite: 'ALTER TABLE `Users` ADD `enum_col` TEXT NOT NULL DEFAULT \'happy\';' + }); + }); + + it('defaults the schema to the one set in the Sequelize options', () => { + return expectsql(customSql.addColumnQuery(User.getTableName(), 'level_id', customSequelize.normalizeAttribute({ + type: DataTypes.FLOAT, + allowNull: false + })), { + mariadb: 'ALTER TABLE `Users` ADD `level_id` FLOAT NOT NULL;', + mysql: 'ALTER TABLE `Users` ADD `level_id` FLOAT NOT NULL;', + postgres: 'ALTER TABLE "custom"."Users" ADD COLUMN "level_id" FLOAT NOT NULL;', + sqlite: 'ALTER TABLE `Users` ADD `level_id` FLOAT NOT NULL;', + mssql: 'ALTER TABLE [Users] ADD [level_id] FLOAT NOT NULL;', + db2: 'ALTER TABLE "Users" ADD "level_id" FLOAT NOT NULL;', + snowflake: 'ALTER TABLE "Users" ADD "level_id" FLOAT NOT NULL;', + oracle: 'ALTER TABLE "Users" ADD "level_id" BINARY_FLOAT NOT NULL' + }); }); }); -} +}); diff --git a/test/unit/sql/add-constraint.test.js b/test/unit/sql/add-constraint.test.js index 3997b4bee74b..082abe0b36cb 100644 --- a/test/unit/sql/add-constraint.test.js +++ b/test/unit/sql/add-constraint.test.js @@ -170,6 +170,7 @@ if (current.dialect.supports.constraints.addConstraint) { }), { db2: 'ALTER TABLE "myTable" ADD CONSTRAINT "myTable_myColumn_anotherColumn_myOtherTable_fk" FOREIGN KEY ("myColumn", "anotherColumn") REFERENCES "myOtherTable" ("id1", "id2") ON DELETE CASCADE;', + oracle: 'ALTER TABLE "myTable" ADD CONSTRAINT "myTable_myColumn_anotherColumn_myOtherTable_fk" FOREIGN KEY ("myColumn", "anotherColumn") REFERENCES "myOtherTable" ("id1", "id2") ON DELETE CASCADE;', default: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn_anotherColumn_myOtherTable_fk] FOREIGN KEY ([myColumn], [anotherColumn]) REFERENCES [myOtherTable] ([id1], [id2]) ON UPDATE CASCADE ON DELETE CASCADE;' } @@ -188,18 +189,33 @@ if (current.dialect.supports.constraints.addConstraint) { onDelete: 'cascade' }), { db2: 'ALTER TABLE "myTable" ADD CONSTRAINT "myTable_myColumn_myOtherTable_fk" FOREIGN KEY ("myColumn") REFERENCES "myOtherTable" ("id") ON DELETE CASCADE;', + oracle: 'ALTER TABLE "myTable" ADD CONSTRAINT "myTable_myColumn_myOtherTable_fk" FOREIGN KEY ("myColumn") REFERENCES "myOtherTable" ("id") ON DELETE CASCADE;', default: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn_myOtherTable_fk] FOREIGN KEY ([myColumn]) REFERENCES [myOtherTable] ([id]) ON UPDATE CASCADE ON DELETE CASCADE;' }); }); + it('uses onDelete: \'no action\'', () => { + expectsql(sql.addConstraintQuery('myTable', { + type: 'foreign key', + fields: ['myColumn'], + references: { + table: 'myOtherTable', + field: 'id' + }, + onUpdate: 'cascade', + onDelete: 'no action' + }), { + oracle: 'ALTER TABLE "myTable" ADD CONSTRAINT "myTable_myColumn_myOtherTable_fk" FOREIGN KEY ("myColumn") REFERENCES "myOtherTable" ("id");', + default: 'ALTER TABLE [myTable] ADD CONSTRAINT [myTable_myColumn_myOtherTable_fk] FOREIGN KEY ([myColumn]) REFERENCES [myOtherTable] ([id]) ON UPDATE CASCADE ON DELETE NO ACTION;' + }); + }); + it('errors if references object is not passed', () => { expect(sql.addConstraintQuery.bind(sql, 'myTable', { type: 'foreign key', fields: ['myColumn'] })).to.throw('references object with table and field must be specified'); }); - - }); describe('validation', () => { diff --git a/test/unit/sql/change-column.test.js b/test/unit/sql/change-column.test.js index 45b734e5c0b8..e6a89d5ddcbf 100644 --- a/test/unit/sql/change-column.test.js +++ b/test/unit/sql/change-column.test.js @@ -44,6 +44,7 @@ if (current.dialect.name !== 'sqlite') { mariadb: 'ALTER TABLE `users` CHANGE `level_id` `level_id` FLOAT NOT NULL;', mysql: 'ALTER TABLE `users` CHANGE `level_id` `level_id` FLOAT NOT NULL;', postgres: 'ALTER TABLE "users" ALTER COLUMN "level_id" SET NOT NULL;ALTER TABLE "users" ALTER COLUMN "level_id" DROP DEFAULT;ALTER TABLE "users" ALTER COLUMN "level_id" TYPE FLOAT;', + oracle: 'DECLARE CONS_NAME VARCHAR2(200); BEGIN BEGIN EXECUTE IMMEDIATE \'ALTER TABLE "users" MODIFY "level_id" BINARY_FLOAT NOT NULL\'; EXCEPTION WHEN OTHERS THEN IF SQLCODE = -1442 OR SQLCODE = -1451 THEN EXECUTE IMMEDIATE \'ALTER TABLE "users" MODIFY "level_id" BINARY_FLOAT \'; ELSE RAISE; END IF; END; END;', snowflake: 'ALTER TABLE "users" ALTER COLUMN "level_id" SET NOT NULL;ALTER TABLE "users" ALTER COLUMN "level_id" DROP DEFAULT;ALTER TABLE "users" ALTER COLUMN "level_id" TYPE FLOAT;' }); }); @@ -60,6 +61,7 @@ if (current.dialect.name !== 'sqlite') { onDelete: 'cascade' }).then(sql => { expectsql(sql, { + oracle: 'DECLARE CONS_NAME VARCHAR2(200); BEGIN BEGIN SELECT constraint_name INTO cons_name FROM (SELECT DISTINCT cc.owner, cc.table_name, cc.constraint_name, cc.column_name AS cons_columns FROM all_cons_columns cc, all_constraints c WHERE cc.owner = c.owner AND cc.table_name = c.table_name AND cc.constraint_name = c.constraint_name AND c.constraint_type = \'R\' GROUP BY cc.owner, cc.table_name, cc.constraint_name, cc.column_name) WHERE owner = USER AND table_name = \'users\' AND cons_columns = \'level_id\' ; EXCEPTION WHEN NO_DATA_FOUND THEN CONS_NAME := NULL; END; IF CONS_NAME IS NOT NULL THEN EXECUTE IMMEDIATE \'ALTER TABLE "users" DROP CONSTRAINT "\'||CONS_NAME||\'"\'; END IF; EXECUTE IMMEDIATE \'ALTER TABLE "users" ADD FOREIGN KEY ("level_id") REFERENCES "level" ("id") ON DELETE CASCADE\'; END;', mssql: 'ALTER TABLE [users] ADD FOREIGN KEY ([level_id]) REFERENCES [level] ([id]) ON DELETE CASCADE;', db2: 'ALTER TABLE "users" ADD CONSTRAINT "level_id_foreign_idx" FOREIGN KEY ("level_id") REFERENCES "level" ("id") ON DELETE CASCADE;', mariadb: 'ALTER TABLE `users` ADD FOREIGN KEY (`level_id`) REFERENCES `level` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;', diff --git a/test/unit/sql/create-schema.test.js b/test/unit/sql/create-schema.test.js index b7e38cb622b6..4ddf66ed13a8 100644 --- a/test/unit/sql/create-schema.test.js +++ b/test/unit/sql/create-schema.test.js @@ -10,7 +10,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { describe('dropSchema', () => { it('IF EXISTS', () => { expectsql(sql.dropSchema('foo'), { - postgres: 'DROP SCHEMA IF EXISTS foo CASCADE;' + postgres: 'DROP SCHEMA IF EXISTS "foo" CASCADE;' }); }); }); @@ -27,14 +27,14 @@ describe(Support.getTestDialectTeaser('SQL'), () => { it('9.2.0 or above', () => { current.options.databaseVersion = '9.2.0'; expectsql(sql.createSchema('foo'), { - postgres: 'CREATE SCHEMA IF NOT EXISTS foo;' + postgres: 'CREATE SCHEMA IF NOT EXISTS "foo";' }); }); it('below 9.2.0', () => { current.options.databaseVersion = '9.0.0'; expectsql(sql.createSchema('foo'), { - postgres: 'CREATE SCHEMA foo;' + postgres: 'CREATE SCHEMA "foo";' }); }); }); diff --git a/test/unit/sql/create-table.test.js b/test/unit/sql/create-table.test.js index 6fccb8b11e74..de2293060c50 100644 --- a/test/unit/sql/create-table.test.js +++ b/test/unit/sql/create-table.test.js @@ -27,6 +27,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'CREATE TABLE IF NOT EXISTS "foo"."users" ("id" SERIAL , "mood" "foo"."enum_users_mood", PRIMARY KEY ("id"));', mariadb: "CREATE TABLE IF NOT EXISTS `foo`.`users` (`id` INTEGER NOT NULL auto_increment , `mood` ENUM('happy', 'sad'), PRIMARY KEY (`id`)) ENGINE=InnoDB;", mysql: "CREATE TABLE IF NOT EXISTS `foo.users` (`id` INTEGER NOT NULL auto_increment , `mood` ENUM('happy', 'sad'), PRIMARY KEY (`id`)) ENGINE=InnoDB;", + oracle: 'BEGIN EXECUTE IMMEDIATE \'CREATE TABLE "foo"."users" ("id" NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY, "mood" VARCHAR2(512) CHECK ("mood" IN(\'\'happy\'\', \'\'sad\'\')),PRIMARY KEY ("id"))\'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;', mssql: "IF OBJECT_ID('[foo].[users]', 'U') IS NULL CREATE TABLE [foo].[users] ([id] INTEGER NOT NULL IDENTITY(1,1) , [mood] VARCHAR(255) CHECK ([mood] IN(N'happy', N'sad')), PRIMARY KEY ([id]));" }); }); @@ -52,6 +53,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { it('references right schema when adding foreign key #9029', () => { expectsql(sql.createTableQuery(BarProject.getTableName(), sql.attributesToSQL(BarProject.rawAttributes), { }), { + oracle: 'BEGIN EXECUTE IMMEDIATE \'CREATE TABLE "bar"."projects" ("id" NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY, "user_id" INTEGER NULL,PRIMARY KEY ("id"),FOREIGN KEY ("user_id") REFERENCES "bar"."users" ("id") )\'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;', sqlite: 'CREATE TABLE IF NOT EXISTS `bar.projects` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `user_id` INTEGER REFERENCES `bar.users` (`id`) ON DELETE NO ACTION ON UPDATE CASCADE);', db2: 'CREATE TABLE "bar"."projects" ("id" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1) , "user_id" INTEGER, PRIMARY KEY ("id"), FOREIGN KEY ("user_id") REFERENCES "bar"."users" ("id") ON DELETE NO ACTION);', postgres: 'CREATE TABLE IF NOT EXISTS "bar"."projects" ("id" SERIAL , "user_id" INTEGER REFERENCES "bar"."users" ("id") ON DELETE NO ACTION ON UPDATE CASCADE, PRIMARY KEY ("id"));', @@ -85,6 +87,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'CREATE TABLE "images" ("id" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY(START WITH 1, INCREMENT BY 1) , PRIMARY KEY ("id"), FOREIGN KEY ("id") REFERENCES "files" ("id"));', mariadb: 'CREATE TABLE IF NOT EXISTS `images` (`id` INTEGER auto_increment , PRIMARY KEY (`id`), FOREIGN KEY (`id`) REFERENCES `files` (`id`)) ENGINE=InnoDB;', mysql: 'CREATE TABLE IF NOT EXISTS `images` (`id` INTEGER auto_increment , PRIMARY KEY (`id`), FOREIGN KEY (`id`) REFERENCES `files` (`id`)) ENGINE=InnoDB;', + oracle: 'BEGIN EXECUTE IMMEDIATE \'CREATE TABLE "images" ("id" NUMBER(*,0) GENERATED BY DEFAULT ON NULL AS IDENTITY ,PRIMARY KEY ("id"),FOREIGN KEY ("id") REFERENCES "files" ("id"))\'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF; END;', mssql: 'IF OBJECT_ID(\'[images]\', \'U\') IS NULL CREATE TABLE [images] ([id] INTEGER IDENTITY(1,1) , PRIMARY KEY ([id]), FOREIGN KEY ([id]) REFERENCES [files] ([id]));' }); }); diff --git a/test/unit/sql/data-types.test.js b/test/unit/sql/data-types.test.js index 2ab7e08f6eb1..17b5436e92dd 100644 --- a/test/unit/sql/data-types.test.js +++ b/test/unit/sql/data-types.test.js @@ -25,17 +25,20 @@ describe(Support.getTestDialectTeaser('SQL'), () => { describe('STRING', () => { testsql('STRING', DataTypes.STRING, { default: 'VARCHAR(255)', - mssql: 'NVARCHAR(255)' + mssql: 'NVARCHAR(255)', + oracle: 'NVARCHAR2(255)' }); testsql('STRING(1234)', DataTypes.STRING(1234), { default: 'VARCHAR(1234)', - mssql: 'NVARCHAR(1234)' + mssql: 'NVARCHAR(1234)', + oracle: 'NVARCHAR2(1234)' }); testsql('STRING({ length: 1234 })', DataTypes.STRING({ length: 1234 }), { default: 'VARCHAR(1234)', - mssql: 'NVARCHAR(1234)' + mssql: 'NVARCHAR(1234)', + oracle: 'NVARCHAR2(1234)' }); testsql('STRING(1234).BINARY', DataTypes.STRING(1234).BINARY, { @@ -43,7 +46,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'VARCHAR(1234) FOR BIT DATA', sqlite: 'VARCHAR BINARY(1234)', mssql: 'BINARY(1234)', - postgres: 'BYTEA' + postgres: 'BYTEA', + oracle: 'RAW(1234)' }); testsql('STRING.BINARY', DataTypes.STRING.BINARY, { @@ -51,7 +55,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'VARCHAR(255) FOR BIT DATA', sqlite: 'VARCHAR BINARY(255)', mssql: 'BINARY(255)', - postgres: 'BYTEA' + postgres: 'BYTEA', + oracle: 'RAW(255)' }); describe('validate', () => { @@ -69,6 +74,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('TEXT', DataTypes.TEXT, { default: 'TEXT', db2: 'VARCHAR(32672)', + oracle: 'CLOB', mssql: 'NVARCHAR(MAX)' // in mssql text is actually representing a non unicode text field }); @@ -77,6 +83,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mssql: 'NVARCHAR(256)', db2: 'VARCHAR(256)', mariadb: 'TINYTEXT', + oracle: 'CLOB', mysql: 'TINYTEXT' }); @@ -85,6 +92,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mssql: 'NVARCHAR(256)', db2: 'VARCHAR(256)', mariadb: 'TINYTEXT', + oracle: 'CLOB', mysql: 'TINYTEXT' }); @@ -93,6 +101,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mssql: 'NVARCHAR(MAX)', db2: 'VARCHAR(8192)', mariadb: 'MEDIUMTEXT', + oracle: 'CLOB', mysql: 'MEDIUMTEXT' }); @@ -101,6 +110,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mssql: 'NVARCHAR(MAX)', db2: 'CLOB(65536)', mariadb: 'LONGTEXT', + oracle: 'CLOB', mysql: 'LONGTEXT' }); @@ -136,12 +146,14 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('CHAR(12).BINARY', DataTypes.CHAR(12).BINARY, { default: 'CHAR(12) BINARY', + oracle: 'RAW(12)', sqlite: 'CHAR BINARY(12)', postgres: 'BYTEA' }); testsql('CHAR.BINARY', DataTypes.CHAR.BINARY, { default: 'CHAR(255) BINARY', + oracle: 'RAW(255)', sqlite: 'CHAR BINARY(255)', postgres: 'BYTEA' }); @@ -155,6 +167,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: 'TINYINT(1)', mysql: 'TINYINT(1)', sqlite: 'TINYINT(1)', + oracle: 'CHAR(1)', snowflake: 'BOOLEAN' }); @@ -188,6 +201,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: 'DATETIME', db2: 'TIMESTAMP', sqlite: 'DATETIME', + oracle: 'TIMESTAMP WITH LOCAL TIME ZONE', snowflake: 'TIMESTAMP' }); @@ -198,6 +212,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: 'DATETIME(6)', db2: 'TIMESTAMP(6)', sqlite: 'DATETIME', + oracle: 'TIMESTAMP WITH LOCAL TIME ZONE', snowflake: 'TIMESTAMP' }); @@ -246,6 +261,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: 'CHAR(36) BINARY', mysql: 'CHAR(36) BINARY', sqlite: 'UUID', + oracle: 'VARCHAR2(36)', snowflake: 'VARCHAR(36)' }); @@ -345,6 +361,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('NOW', DataTypes.NOW, { default: 'NOW', db2: 'CURRENT TIME', + oracle: 'SYSDATE', mssql: 'GETDATE()' }); }); @@ -359,7 +376,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'INTEGER', db2: 'INTEGER', mssql: 'INTEGER', - sqlite: 'INTEGER' + sqlite: 'INTEGER', + oracle: 'INTEGER' }); testsql('INTEGER.UNSIGNED.ZEROFILL', DataTypes.INTEGER.UNSIGNED.ZEROFILL, { @@ -367,21 +385,24 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'INTEGER', db2: 'INTEGER', mssql: 'INTEGER', - sqlite: 'INTEGER' + sqlite: 'INTEGER', + oracle: 'INTEGER' }); testsql('INTEGER(11)', DataTypes.INTEGER(11), { default: 'INTEGER(11)', postgres: 'INTEGER', db2: 'INTEGER', - mssql: 'INTEGER' + mssql: 'INTEGER', + oracle: 'NUMBER(11,0)' }); testsql('INTEGER({ length: 11 })', DataTypes.INTEGER({ length: 11 }), { default: 'INTEGER(11)', postgres: 'INTEGER', db2: 'INTEGER', - mssql: 'INTEGER' + mssql: 'INTEGER', + oracle: 'NUMBER(11,0)' }); testsql('INTEGER(11).UNSIGNED', DataTypes.INTEGER(11).UNSIGNED, { @@ -389,7 +410,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'INTEGER(11)', postgres: 'INTEGER', db2: 'INTEGER', - mssql: 'INTEGER' + mssql: 'INTEGER', + oracle: 'NUMBER(11,0)' }); testsql('INTEGER(11).UNSIGNED.ZEROFILL', DataTypes.INTEGER(11).UNSIGNED.ZEROFILL, { @@ -397,7 +419,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'INTEGER(11)', postgres: 'INTEGER', db2: 'INTEGER', - mssql: 'INTEGER' + mssql: 'INTEGER', + oracle: 'NUMBER(11,0)' }); testsql('INTEGER(11).ZEROFILL', DataTypes.INTEGER(11).ZEROFILL, { @@ -405,7 +428,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'INTEGER(11)', postgres: 'INTEGER', db2: 'INTEGER', - mssql: 'INTEGER' + mssql: 'INTEGER', + oracle: 'NUMBER(11,0)' }); testsql('INTEGER(11).ZEROFILL.UNSIGNED', DataTypes.INTEGER(11).ZEROFILL.UNSIGNED, { @@ -413,7 +437,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'INTEGER(11)', postgres: 'INTEGER', db2: 'INTEGER', - mssql: 'INTEGER' + mssql: 'INTEGER', + oracle: 'NUMBER(11,0)' }); describe('validate', () => { @@ -448,6 +473,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { title: 'TINYINT', dataType: DataTypes.TINYINT, expect: { + oracle: 'NUMBER(3)', default: 'TINYINT' } }, @@ -457,6 +483,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expect: { default: 'TINYINT(2)', db2: 'TINYINT', + oracle: 'NUMBER(3)', mssql: 'TINYINT', postgres: 'TINYINT' } @@ -467,6 +494,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expect: { default: 'TINYINT(2)', db2: 'TINYINT', + oracle: 'NUMBER(3)', mssql: 'TINYINT', postgres: 'TINYINT' } @@ -477,6 +505,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expect: { default: 'TINYINT UNSIGNED', db2: 'TINYINT', + oracle: 'NUMBER(3)', mssql: 'TINYINT', postgres: 'TINYINT', sqlite: 'TINYINT' @@ -488,6 +517,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expect: { default: 'TINYINT(2) UNSIGNED', db2: 'TINYINT', + oracle: 'NUMBER(3)', sqlite: 'TINYINT(2)', mssql: 'TINYINT', postgres: 'TINYINT' @@ -499,6 +529,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expect: { default: 'TINYINT UNSIGNED ZEROFILL', db2: 'TINYINT', + oracle: 'NUMBER(3)', mssql: 'TINYINT', postgres: 'TINYINT', sqlite: 'TINYINT' @@ -510,6 +541,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expect: { default: 'TINYINT(2) UNSIGNED ZEROFILL', db2: 'TINYINT', + oracle: 'NUMBER(3)', sqlite: 'TINYINT(2)', mssql: 'TINYINT', postgres: 'TINYINT' @@ -521,6 +553,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expect: { default: 'TINYINT ZEROFILL', db2: 'TINYINT', + oracle: 'NUMBER(3)', mssql: 'TINYINT', postgres: 'TINYINT', sqlite: 'TINYINT' @@ -532,6 +565,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expect: { default: 'TINYINT(2) ZEROFILL', db2: 'TINYINT', + oracle: 'NUMBER(3)', sqlite: 'TINYINT(2)', mssql: 'TINYINT', postgres: 'TINYINT' @@ -543,6 +577,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expect: { default: 'TINYINT UNSIGNED ZEROFILL', db2: 'TINYINT', + oracle: 'NUMBER(3)', mssql: 'TINYINT', postgres: 'TINYINT', sqlite: 'TINYINT' @@ -554,6 +589,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expect: { default: 'TINYINT(2) UNSIGNED ZEROFILL', db2: 'TINYINT', + oracle: 'NUMBER(3)', sqlite: 'TINYINT(2)', mssql: 'TINYINT', postgres: 'TINYINT' @@ -600,6 +636,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.SMALLINT(4), expect: { default: 'SMALLINT(4)', + oracle: 'NUMBER(4,0)', postgres: 'SMALLINT', db2: 'SMALLINT', mssql: 'SMALLINT' @@ -610,6 +647,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.SMALLINT({ length: 4 }), expect: { default: 'SMALLINT(4)', + oracle: 'NUMBER(4,0)', postgres: 'SMALLINT', db2: 'SMALLINT', mssql: 'SMALLINT' @@ -620,6 +658,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.SMALLINT.UNSIGNED, expect: { default: 'SMALLINT UNSIGNED', + oracle: 'SMALLINT', postgres: 'SMALLINT', db2: 'SMALLINT', mssql: 'SMALLINT', @@ -631,6 +670,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.SMALLINT(4).UNSIGNED, expect: { default: 'SMALLINT(4) UNSIGNED', + oracle: 'NUMBER(4,0)', sqlite: 'SMALLINT(4)', postgres: 'SMALLINT', db2: 'SMALLINT', @@ -642,6 +682,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.SMALLINT.UNSIGNED.ZEROFILL, expect: { default: 'SMALLINT UNSIGNED ZEROFILL', + oracle: 'SMALLINT', postgres: 'SMALLINT', db2: 'SMALLINT', mssql: 'SMALLINT', @@ -653,6 +694,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.SMALLINT(4).UNSIGNED.ZEROFILL, expect: { default: 'SMALLINT(4) UNSIGNED ZEROFILL', + oracle: 'NUMBER(4,0)', sqlite: 'SMALLINT(4)', postgres: 'SMALLINT', db2: 'SMALLINT', @@ -664,6 +706,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.SMALLINT.ZEROFILL, expect: { default: 'SMALLINT ZEROFILL', + oracle: 'SMALLINT', postgres: 'SMALLINT', db2: 'SMALLINT', mssql: 'SMALLINT', @@ -675,6 +718,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.SMALLINT(4).ZEROFILL, expect: { default: 'SMALLINT(4) ZEROFILL', + oracle: 'NUMBER(4,0)', sqlite: 'SMALLINT(4)', postgres: 'SMALLINT', db2: 'SMALLINT', @@ -686,6 +730,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.SMALLINT.ZEROFILL.UNSIGNED, expect: { default: 'SMALLINT UNSIGNED ZEROFILL', + oracle: 'SMALLINT', postgres: 'SMALLINT', db2: 'SMALLINT', mssql: 'SMALLINT', @@ -697,6 +742,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.SMALLINT(4).ZEROFILL.UNSIGNED, expect: { default: 'SMALLINT(4) UNSIGNED ZEROFILL', + oracle: 'NUMBER(4,0)', sqlite: 'SMALLINT(4)', postgres: 'SMALLINT', db2: 'SMALLINT', @@ -736,6 +782,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { title: 'MEDIUMINT', dataType: DataTypes.MEDIUMINT, expect: { + oracle: 'NUMBER(8)', default: 'MEDIUMINT' } }, @@ -743,6 +790,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { title: 'MEDIUMINT(6)', dataType: DataTypes.MEDIUMINT(6), expect: { + oracle: 'NUMBER(8)', default: 'MEDIUMINT(6)' } }, @@ -750,6 +798,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { title: 'MEDIUMINT({ length: 6 })', dataType: DataTypes.MEDIUMINT({ length: 6 }), expect: { + oracle: 'NUMBER(8)', default: 'MEDIUMINT(6)' } }, @@ -758,6 +807,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.MEDIUMINT.UNSIGNED, expect: { default: 'MEDIUMINT UNSIGNED', + oracle: 'NUMBER(8)', sqlite: 'MEDIUMINT' } }, @@ -766,6 +816,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.MEDIUMINT(6).UNSIGNED, expect: { default: 'MEDIUMINT(6) UNSIGNED', + oracle: 'NUMBER(8)', sqlite: 'MEDIUMINT(6)' } }, @@ -774,6 +825,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.MEDIUMINT.UNSIGNED.ZEROFILL, expect: { default: 'MEDIUMINT UNSIGNED ZEROFILL', + oracle: 'NUMBER(8)', sqlite: 'MEDIUMINT' } }, @@ -782,6 +834,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.MEDIUMINT(6).UNSIGNED.ZEROFILL, expect: { default: 'MEDIUMINT(6) UNSIGNED ZEROFILL', + oracle: 'NUMBER(8)', sqlite: 'MEDIUMINT(6)' } }, @@ -790,6 +843,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.MEDIUMINT.ZEROFILL, expect: { default: 'MEDIUMINT ZEROFILL', + oracle: 'NUMBER(8)', sqlite: 'MEDIUMINT' } }, @@ -798,6 +852,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.MEDIUMINT(6).ZEROFILL, expect: { default: 'MEDIUMINT(6) ZEROFILL', + oracle: 'NUMBER(8)', sqlite: 'MEDIUMINT(6)' } }, @@ -806,6 +861,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.MEDIUMINT.ZEROFILL.UNSIGNED, expect: { default: 'MEDIUMINT UNSIGNED ZEROFILL', + oracle: 'NUMBER(8)', sqlite: 'MEDIUMINT' } }, @@ -814,6 +870,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { dataType: DataTypes.MEDIUMINT(6).ZEROFILL.UNSIGNED, expect: { default: 'MEDIUMINT(6) UNSIGNED ZEROFILL', + oracle: 'NUMBER(8)', sqlite: 'MEDIUMINT(6)' } } @@ -846,7 +903,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { describe('BIGINT', () => { testsql('BIGINT', DataTypes.BIGINT, { - default: 'BIGINT' + default: 'BIGINT', + oracle: 'NUMBER(19)' }); testsql('BIGINT.UNSIGNED', DataTypes.BIGINT.UNSIGNED, { @@ -854,7 +912,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'BIGINT', db2: 'BIGINT', mssql: 'BIGINT', - sqlite: 'BIGINT' + sqlite: 'BIGINT', + oracle: 'NUMBER(19)' }); testsql('BIGINT.UNSIGNED.ZEROFILL', DataTypes.BIGINT.UNSIGNED.ZEROFILL, { @@ -862,13 +921,15 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'BIGINT', db2: 'BIGINT', mssql: 'BIGINT', - sqlite: 'BIGINT' + sqlite: 'BIGINT', + oracle: 'NUMBER(19)' }); testsql('BIGINT(11)', DataTypes.BIGINT(11), { default: 'BIGINT(11)', postgres: 'BIGINT', db2: 'BIGINT', + oracle: 'NUMBER(19)', mssql: 'BIGINT' }); @@ -876,6 +937,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'BIGINT(11)', postgres: 'BIGINT', db2: 'BIGINT', + oracle: 'NUMBER(19)', mssql: 'BIGINT' }); @@ -884,6 +946,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'BIGINT(11)', postgres: 'BIGINT', db2: 'BIGINT', + oracle: 'NUMBER(19)', mssql: 'BIGINT' }); @@ -892,6 +955,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'BIGINT(11)', postgres: 'BIGINT', db2: 'BIGINT', + oracle: 'NUMBER(19)', mssql: 'BIGINT' }); @@ -900,6 +964,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'BIGINT(11)', postgres: 'BIGINT', db2: 'BIGINT', + oracle: 'NUMBER(19)', mssql: 'BIGINT' }); @@ -908,6 +973,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'BIGINT(11)', postgres: 'BIGINT', db2: 'BIGINT', + oracle: 'NUMBER(19)', mssql: 'BIGINT' }); @@ -934,6 +1000,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { describe('REAL', () => { testsql('REAL', DataTypes.REAL, { + oracle: 'BINARY_DOUBLE', default: 'REAL' }); @@ -941,6 +1008,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'REAL UNSIGNED', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -948,6 +1016,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'REAL(11)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -955,6 +1024,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'REAL(11)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -963,6 +1033,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'REAL UNSIGNED(11)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -971,6 +1042,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'REAL UNSIGNED ZEROFILL(11)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -979,6 +1051,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'REAL ZEROFILL(11)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -987,6 +1060,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'REAL UNSIGNED ZEROFILL(11)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -994,6 +1068,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'REAL(11,12)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -1002,6 +1077,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'REAL UNSIGNED(11,12)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -1010,6 +1086,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'REAL UNSIGNED(11,12)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -1018,6 +1095,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'REAL UNSIGNED ZEROFILL(11,12)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -1026,6 +1104,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'REAL ZEROFILL(11,12)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); @@ -1034,6 +1113,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'REAL UNSIGNED ZEROFILL(11,12)', postgres: 'REAL', db2: 'REAL', + oracle: 'BINARY_DOUBLE', mssql: 'REAL' }); }); @@ -1041,18 +1121,21 @@ describe(Support.getTestDialectTeaser('SQL'), () => { describe('DOUBLE PRECISION', () => { testsql('DOUBLE', DataTypes.DOUBLE, { db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', default: 'DOUBLE PRECISION' }); testsql('DOUBLE.UNSIGNED', DataTypes.DOUBLE.UNSIGNED, { default: 'DOUBLE PRECISION UNSIGNED', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); testsql('DOUBLE(11)', DataTypes.DOUBLE(11), { default: 'DOUBLE PRECISION(11)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); @@ -1060,6 +1143,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'DOUBLE PRECISION(11) UNSIGNED', sqlite: 'DOUBLE PRECISION UNSIGNED(11)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); @@ -1067,6 +1151,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'DOUBLE PRECISION(11) UNSIGNED', sqlite: 'DOUBLE PRECISION UNSIGNED(11)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); @@ -1074,6 +1159,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'DOUBLE PRECISION(11) UNSIGNED ZEROFILL', sqlite: 'DOUBLE PRECISION UNSIGNED ZEROFILL(11)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); @@ -1081,6 +1167,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'DOUBLE PRECISION(11) ZEROFILL', sqlite: 'DOUBLE PRECISION ZEROFILL(11)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); @@ -1088,12 +1175,14 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'DOUBLE PRECISION(11) UNSIGNED ZEROFILL', sqlite: 'DOUBLE PRECISION UNSIGNED ZEROFILL(11)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); testsql('DOUBLE(11, 12)', DataTypes.DOUBLE(11, 12), { default: 'DOUBLE PRECISION(11,12)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); @@ -1101,6 +1190,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'DOUBLE PRECISION(11,12) UNSIGNED', sqlite: 'DOUBLE PRECISION UNSIGNED(11,12)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); @@ -1108,6 +1198,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'DOUBLE PRECISION(11,12) UNSIGNED ZEROFILL', sqlite: 'DOUBLE PRECISION UNSIGNED ZEROFILL(11,12)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); @@ -1115,6 +1206,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'DOUBLE PRECISION(11,12) ZEROFILL', sqlite: 'DOUBLE PRECISION ZEROFILL(11,12)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); @@ -1122,6 +1214,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { default: 'DOUBLE PRECISION(11,12) UNSIGNED ZEROFILL', sqlite: 'DOUBLE PRECISION UNSIGNED ZEROFILL(11,12)', db2: 'DOUBLE', + oracle: 'BINARY_DOUBLE', postgres: 'DOUBLE PRECISION' }); }); @@ -1129,11 +1222,13 @@ describe(Support.getTestDialectTeaser('SQL'), () => { describe('FLOAT', () => { testsql('FLOAT', DataTypes.FLOAT, { default: 'FLOAT', + oracle: 'BINARY_FLOAT', postgres: 'FLOAT' }); testsql('FLOAT.UNSIGNED', DataTypes.FLOAT.UNSIGNED, { default: 'FLOAT UNSIGNED', + oracle: 'BINARY_FLOAT', postgres: 'FLOAT', db2: 'FLOAT', mssql: 'FLOAT' @@ -1141,6 +1236,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT(11)', DataTypes.FLOAT(11), { default: 'FLOAT(11)', + oracle: 'BINARY_FLOAT', postgres: 'FLOAT(11)', // 1-24 = 4 bytes; 35-53 = 8 bytes db2: 'FLOAT(11)', // 1-24 = 4 bytes; 35-53 = 8 bytes mssql: 'FLOAT(11)' // 1-24 = 4 bytes; 35-53 = 8 bytes @@ -1148,6 +1244,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT(11).UNSIGNED', DataTypes.FLOAT(11).UNSIGNED, { default: 'FLOAT(11) UNSIGNED', + oracle: 'BINARY_FLOAT', sqlite: 'FLOAT UNSIGNED(11)', postgres: 'FLOAT(11)', db2: 'FLOAT(11)', @@ -1156,6 +1253,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT(11).UNSIGNED.ZEROFILL', DataTypes.FLOAT(11).UNSIGNED.ZEROFILL, { default: 'FLOAT(11) UNSIGNED ZEROFILL', + oracle: 'BINARY_FLOAT', sqlite: 'FLOAT UNSIGNED ZEROFILL(11)', postgres: 'FLOAT(11)', db2: 'FLOAT(11)', @@ -1164,6 +1262,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT(11).ZEROFILL', DataTypes.FLOAT(11).ZEROFILL, { default: 'FLOAT(11) ZEROFILL', + oracle: 'BINARY_FLOAT', sqlite: 'FLOAT ZEROFILL(11)', postgres: 'FLOAT(11)', db2: 'FLOAT(11)', @@ -1172,6 +1271,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT({ length: 11 }).ZEROFILL', DataTypes.FLOAT({ length: 11 }).ZEROFILL, { default: 'FLOAT(11) ZEROFILL', + oracle: 'BINARY_FLOAT', sqlite: 'FLOAT ZEROFILL(11)', postgres: 'FLOAT(11)', db2: 'FLOAT(11)', @@ -1180,6 +1280,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT(11).ZEROFILL.UNSIGNED', DataTypes.FLOAT(11).ZEROFILL.UNSIGNED, { default: 'FLOAT(11) UNSIGNED ZEROFILL', + oracle: 'BINARY_FLOAT', sqlite: 'FLOAT UNSIGNED ZEROFILL(11)', postgres: 'FLOAT(11)', db2: 'FLOAT(11)', @@ -1188,6 +1289,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT(11, 12)', DataTypes.FLOAT(11, 12), { default: 'FLOAT(11,12)', + oracle: 'BINARY_FLOAT', postgres: 'FLOAT', db2: 'FLOAT', mssql: 'FLOAT' @@ -1195,6 +1297,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT(11, 12).UNSIGNED', DataTypes.FLOAT(11, 12).UNSIGNED, { default: 'FLOAT(11,12) UNSIGNED', + oracle: 'BINARY_FLOAT', sqlite: 'FLOAT UNSIGNED(11,12)', postgres: 'FLOAT', db2: 'FLOAT', @@ -1203,6 +1306,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT({ length: 11, decimals: 12 }).UNSIGNED', DataTypes.FLOAT({ length: 11, decimals: 12 }).UNSIGNED, { default: 'FLOAT(11,12) UNSIGNED', + oracle: 'BINARY_FLOAT', sqlite: 'FLOAT UNSIGNED(11,12)', postgres: 'FLOAT', db2: 'FLOAT', @@ -1211,6 +1315,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT(11, 12).UNSIGNED.ZEROFILL', DataTypes.FLOAT(11, 12).UNSIGNED.ZEROFILL, { default: 'FLOAT(11,12) UNSIGNED ZEROFILL', + oracle: 'BINARY_FLOAT', sqlite: 'FLOAT UNSIGNED ZEROFILL(11,12)', postgres: 'FLOAT', db2: 'FLOAT', @@ -1219,6 +1324,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT(11, 12).ZEROFILL', DataTypes.FLOAT(11, 12).ZEROFILL, { default: 'FLOAT(11,12) ZEROFILL', + oracle: 'BINARY_FLOAT', sqlite: 'FLOAT ZEROFILL(11,12)', postgres: 'FLOAT', db2: 'FLOAT', @@ -1227,6 +1333,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('FLOAT(11, 12).ZEROFILL.UNSIGNED', DataTypes.FLOAT(11, 12).ZEROFILL.UNSIGNED, { default: 'FLOAT(11,12) UNSIGNED ZEROFILL', + oracle: 'BINARY_FLOAT', sqlite: 'FLOAT UNSIGNED ZEROFILL(11,12)', postgres: 'FLOAT', db2: 'FLOAT', @@ -1256,51 +1363,61 @@ describe(Support.getTestDialectTeaser('SQL'), () => { if (current.dialect.supports.NUMERIC) { testsql('NUMERIC', DataTypes.NUMERIC, { - default: 'DECIMAL' + default: 'DECIMAL', + oracle: 'NUMBER' }); testsql('NUMERIC(15,5)', DataTypes.NUMERIC(15, 5), { - default: 'DECIMAL(15,5)' + default: 'DECIMAL(15,5)', + oracle: 'NUMBER(15,5)' }); } describe('DECIMAL', () => { testsql('DECIMAL', DataTypes.DECIMAL, { - default: 'DECIMAL' + default: 'DECIMAL', + oracle: 'NUMBER' }); testsql('DECIMAL(10, 2)', DataTypes.DECIMAL(10, 2), { - default: 'DECIMAL(10,2)' + default: 'DECIMAL(10,2)', + oracle: 'NUMBER(10,2)' }); testsql('DECIMAL({ precision: 10, scale: 2 })', DataTypes.DECIMAL({ precision: 10, scale: 2 }), { - default: 'DECIMAL(10,2)' + default: 'DECIMAL(10,2)', + oracle: 'NUMBER(10,2)' }); testsql('DECIMAL(10)', DataTypes.DECIMAL(10), { - default: 'DECIMAL(10)' + default: 'DECIMAL(10)', + oracle: 'NUMBER(10)' }); testsql('DECIMAL({ precision: 10 })', DataTypes.DECIMAL({ precision: 10 }), { - default: 'DECIMAL(10)' + default: 'DECIMAL(10)', + oracle: 'NUMBER(10)' }); testsql('DECIMAL.UNSIGNED', DataTypes.DECIMAL.UNSIGNED, { mariadb: 'DECIMAL UNSIGNED', mysql: 'DECIMAL UNSIGNED', - default: 'DECIMAL' + default: 'DECIMAL', + oracle: 'NUMBER' }); testsql('DECIMAL.UNSIGNED.ZEROFILL', DataTypes.DECIMAL.UNSIGNED.ZEROFILL, { mariadb: 'DECIMAL UNSIGNED ZEROFILL', mysql: 'DECIMAL UNSIGNED ZEROFILL', - default: 'DECIMAL' + default: 'DECIMAL', + oracle: 'NUMBER' }); testsql('DECIMAL({ precision: 10, scale: 2 }).UNSIGNED', DataTypes.DECIMAL({ precision: 10, scale: 2 }).UNSIGNED, { mariadb: 'DECIMAL(10,2) UNSIGNED', mysql: 'DECIMAL(10,2) UNSIGNED', - default: 'DECIMAL(10,2)' + default: 'DECIMAL(10,2)', + oracle: 'NUMBER(10,2)' }); describe('validate', () => { @@ -1368,6 +1485,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('BLOB("tiny")', DataTypes.BLOB('tiny'), { default: 'TINYBLOB', + oracle: 'BLOB', mssql: 'VARBINARY(256)', db2: 'BLOB(255)', postgres: 'BYTEA' @@ -1375,6 +1493,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('BLOB("medium")', DataTypes.BLOB('medium'), { default: 'MEDIUMBLOB', + oracle: 'BLOB', mssql: 'VARBINARY(MAX)', db2: 'BLOB(16M)', postgres: 'BYTEA' @@ -1382,6 +1501,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('BLOB({ length: "medium" })', DataTypes.BLOB({ length: 'medium' }), { default: 'MEDIUMBLOB', + oracle: 'BLOB', mssql: 'VARBINARY(MAX)', db2: 'BLOB(16M)', postgres: 'BYTEA' @@ -1389,6 +1509,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { testsql('BLOB("long")', DataTypes.BLOB('long'), { default: 'LONGBLOB', + oracle: 'BLOB', mssql: 'VARBINARY(MAX)', db2: 'BLOB(2G)', postgres: 'BYTEA' diff --git a/test/unit/sql/delete.test.js b/test/unit/sql/delete.test.js index 2e0d341108a8..ec34bd5236c6 100644 --- a/test/unit/sql/delete.test.js +++ b/test/unit/sql/delete.test.js @@ -40,6 +40,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: 'TRUNCATE `public.test_users`', db2: 'TRUNCATE TABLE "public"."test_users" IMMEDIATE', sqlite: 'DELETE FROM `public.test_users`', + oracle: 'TRUNCATE TABLE "public"."test_users"', snowflake: 'TRUNCATE "public"."test_users"' } ); @@ -69,6 +70,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: 'TRUNCATE `public.test_users`', db2: 'TRUNCATE TABLE "public"."test_users" IMMEDIATE', sqlite: 'DELETE FROM `public.test_users`; DELETE FROM `sqlite_sequence` WHERE `name` = \'public.test_users\';', + oracle: 'TRUNCATE TABLE "public"."test_users"', snowflake: 'TRUNCATE "public"."test_users"' } ); @@ -97,6 +99,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: "DELETE FROM `public.test_users` WHERE `name` = 'foo'", db2: 'DELETE FROM "public"."test_users" WHERE "name" = \'foo\'', mssql: "DELETE FROM [public].[test_users] WHERE [name] = N'foo'; SELECT @@ROWCOUNT AS AFFECTEDROWS;", + oracle: 'DELETE FROM "public"."test_users" WHERE "name" = \'foo\'', snowflake: 'DELETE FROM "public"."test_users" WHERE "name" = \'foo\';' } ); @@ -125,6 +128,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mssql: "DELETE TOP(10) FROM [public].[test_users] WHERE [name] = N'foo'';DROP TABLE mySchema.myTable;'; SELECT @@ROWCOUNT AS AFFECTEDROWS;", db2: "DELETE FROM \"public\".\"test_users\" WHERE \"name\" = 'foo'';DROP TABLE mySchema.myTable;' FETCH NEXT 10 ROWS ONLY", snowflake: 'DELETE FROM "public"."test_users" WHERE "id" IN (SELECT "id" FROM "public"."test_users" WHERE "name" = \'foo\'\';DROP TABLE mySchema.myTable;\' LIMIT 10);', + oracle: 'DELETE FROM "public"."test_users" WHERE rowid IN (SELECT rowid FROM "public"."test_users" WHERE rownum <= 10 AND "name" = \'foo\'\';DROP TABLE mySchema.myTable;\')', default: "DELETE FROM [public.test_users] WHERE `name` = 'foo\\';DROP TABLE mySchema.myTable;' LIMIT 10" } ); @@ -159,6 +163,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: "DELETE FROM `public.test_users` WHERE rowid IN (SELECT rowid FROM `public.test_users` WHERE `name` = 'foo'';DROP TABLE mySchema.myTable;' LIMIT 10)", mssql: "DELETE TOP(10) FROM [public].[test_users] WHERE [name] = N'foo'';DROP TABLE mySchema.myTable;'; SELECT @@ROWCOUNT AS AFFECTEDROWS;", db2: "DELETE FROM \"public\".\"test_users\" WHERE \"name\" = 'foo'';DROP TABLE mySchema.myTable;' FETCH NEXT 10 ROWS ONLY", + oracle: 'DELETE FROM "public"."test_users" WHERE rowid IN (SELECT rowid FROM "public"."test_users" WHERE rownum <= 10 AND "name" = \'foo\'\';DROP TABLE mySchema.myTable;\')', snowflake: new Error('Cannot LIMIT delete without a model.'), default: "DELETE FROM [public.test_users] WHERE `name` = 'foo\\';DROP TABLE mySchema.myTable;' LIMIT 10" } diff --git a/test/unit/sql/enum.test.js b/test/unit/sql/enum.test.js index a6e13a23d32f..c27836281a04 100644 --- a/test/unit/sql/enum.test.js +++ b/test/unit/sql/enum.test.js @@ -43,13 +43,13 @@ describe(Support.getTestDialectTeaser('SQL'), () => { describe('pgEnum', () => { it('uses schema #3171', () => { expectsql(sql.pgEnum(FooUser.getTableName(), 'mood', FooUser.rawAttributes.mood.type), { - postgres: 'CREATE TYPE "foo"."enum_users_mood" AS ENUM(\'happy\', \'sad\');' + postgres: 'DO \'BEGIN CREATE TYPE "foo"."enum_users_mood" AS ENUM(\'\'happy\'\', \'\'sad\'\'); EXCEPTION WHEN duplicate_object THEN null; END\';' }); }); it('does add schema when public', () => { expectsql(sql.pgEnum(PublicUser.getTableName(), 'theirMood', PublicUser.rawAttributes.mood.type), { - postgres: 'CREATE TYPE "public"."enum_users_theirMood" AS ENUM(\'happy\', \'sad\');' + postgres: 'DO \'BEGIN CREATE TYPE "public"."enum_users_theirMood" AS ENUM(\'\'happy\'\', \'\'sad\'\'); EXCEPTION WHEN duplicate_object THEN null; END\';' }); }); }); diff --git a/test/unit/sql/generateJoin.test.js b/test/unit/sql/generateJoin.test.js index 5283d048ba14..29e6cbf28964 100644 --- a/test/unit/sql/generateJoin.test.js +++ b/test/unit/sql/generateJoin.test.js @@ -99,7 +99,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ] }, { - default: 'LEFT OUTER JOIN [company] AS [Company] ON [User].[company_id] = [Company].[id]' + default: 'LEFT OUTER JOIN [company] AS [Company] ON [User].[company_id] = [Company].[id]', + oracle: 'LEFT OUTER JOIN "company" "Company" ON "User"."company_id" = "Company"."id"' } ); @@ -118,6 +119,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { { default: 'INNER JOIN [company] AS [Company] ON [User].[company_id] = [Company].[id] OR [Company].[public] = true', sqlite: 'INNER JOIN `company` AS `Company` ON `User`.`company_id` = `Company`.`id` OR `Company`.`public` = 1', + oracle: 'INNER JOIN "company" "Company" ON "User"."company_id" = "Company"."id" OR "Company"."public" = \'1\'', mssql: 'INNER JOIN [company] AS [Company] ON [User].[company_id] = [Company].[id] OR [Company].[public] = 1' } ); @@ -137,6 +139,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ] }, { + oracle: 'LEFT OUTER JOIN "company" "Professionals->Company" ON "Professionals"."company_id" = "Professionals->Company"."id"', default: 'LEFT OUTER JOIN [company] AS [Professionals->Company] ON [Professionals].[company_id] = [Professionals->Company].[id]' } ); @@ -151,7 +154,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ] }, { - default: 'LEFT OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]' + default: 'LEFT OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]', + oracle: 'LEFT OUTER JOIN "company" "Company" ON "User"."companyId" = "Company"."id"' } ); @@ -168,6 +172,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, { default: "LEFT OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id] AND [Company].[name] = 'ABC'", + oracle: 'LEFT OUTER JOIN "company" "Company" ON "User"."companyId" = "Company"."id" AND "Company"."name" = \'ABC\'', mssql: "LEFT OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id] AND [Company].[name] = N'ABC'" } ); @@ -184,7 +189,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ] }, { - default: `${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]` + default: `${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]`, + oracle: 'RIGHT OUTER JOIN "company" "Company" ON "User"."companyId" = "Company"."id"' } ); @@ -203,7 +209,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, { - default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON [Company].[owner_id] = [Company->Owner].[id_user]' + default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON [Company].[owner_id] = [Company->Owner].[id_user]', + oracle: 'LEFT OUTER JOIN "user" "Company->Owner" ON "Company"."owner_id" = "Company->Owner"."id_user"' } ); @@ -224,7 +231,10 @@ describe(Support.getTestDialectTeaser('SQL'), () => { } ] }, - { default: 'LEFT OUTER JOIN [profession] AS [Company->Owner->Profession] ON [Company->Owner].[professionId] = [Company->Owner->Profession].[id]' } + { + default: 'LEFT OUTER JOIN [profession] AS [Company->Owner->Profession] ON [Company->Owner].[professionId] = [Company->Owner->Profession].[id]', + oracle: 'LEFT OUTER JOIN "profession" "Company->Owner->Profession" ON "Company->Owner"."professionId" = "Company->Owner->Profession"."id"' + } ); testsql( @@ -242,7 +252,10 @@ describe(Support.getTestDialectTeaser('SQL'), () => { } ] }, - { default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON [Company].[owner_id] = [Company->Owner].[id_user]' } + { + default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON [Company].[owner_id] = [Company->Owner].[id_user]', + oracle: 'LEFT OUTER JOIN "user" "Company->Owner" ON "Company"."owner_id" = "Company->Owner"."id_user"' + } ); testsql( @@ -255,7 +268,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ] }, { - default: 'INNER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]' + default: 'INNER JOIN [company] AS [Company] ON [User].[companyId] = [Company].[id]', + oracle: 'INNER JOIN "company" "Company" ON "User"."companyId" = "Company"."id"' } ); @@ -271,7 +285,10 @@ describe(Support.getTestDialectTeaser('SQL'), () => { User.Tasks ] }, - { default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id_user] = [Tasks].[user_id]' } + { + default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id_user] = [Tasks].[user_id]', + oracle: 'LEFT OUTER JOIN "task" "Tasks" ON "User"."id_user" = "Tasks"."user_id"' + } ); testsql( @@ -285,7 +302,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, { // The primary key of the main model will be aliased because it's coming from a subquery that the :M join is not a part of - default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id] = [Tasks].[user_id]' + default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [User].[id] = [Tasks].[user_id]', + oracle: 'LEFT OUTER JOIN "task" "Tasks" ON "User"."id" = "Tasks"."user_id"' } ); @@ -303,7 +321,11 @@ describe(Support.getTestDialectTeaser('SQL'), () => { } } ] - }, { default: 'LEFT OUTER JOIN [task] AS [Tasks] ON ([User].[id_user] = [Tasks].[user_id] OR [Tasks].[user_id] = 2)' } + }, + { + default: 'LEFT OUTER JOIN [task] AS [Tasks] ON ([User].[id_user] = [Tasks].[user_id] OR [Tasks].[user_id] = 2)', + oracle: 'LEFT OUTER JOIN "task" "Tasks" ON ("User"."id_user" = "Tasks"."user_id" OR "Tasks"."user_id" = 2)' + } ); testsql( @@ -316,7 +338,11 @@ describe(Support.getTestDialectTeaser('SQL'), () => { on: { 'user_id': { [Op.col]: 'User.alternative_id' } } } ] - }, { default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [Tasks].[user_id] = [User].[alternative_id]' } + }, + { + default: 'LEFT OUTER JOIN [task] AS [Tasks] ON [Tasks].[user_id] = [User].[alternative_id]', + oracle: 'LEFT OUTER JOIN "task" "Tasks" ON "Tasks"."user_id" = "User"."alternative_id"' + } ); testsql( @@ -343,7 +369,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, { - default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON ([Company].[owner_id] = [Company->Owner].[id_user] OR [Company->Owner].[id_user] = 2)' + default: 'LEFT OUTER JOIN [user] AS [Company->Owner] ON ([Company].[owner_id] = [Company->Owner].[id_user] OR [Company->Owner].[id_user] = 2)', + oracle: 'LEFT OUTER JOIN "user" "Company->Owner" ON ("Company"."owner_id" = "Company->Owner"."id_user" OR "Company->Owner"."id_user" = 2)' } ); diff --git a/test/unit/sql/get-where-conditions.test.js b/test/unit/sql/get-where-conditions.test.js new file mode 100644 index 000000000000..88578738955e --- /dev/null +++ b/test/unit/sql/get-where-conditions.test.js @@ -0,0 +1,26 @@ +const { expect } = require('chai'); +const { sequelize } = require('../../support'); + +describe('QueryGenerator#getWhereConditions', () => { + const queryGenerator = sequelize.queryInterface.queryGenerator; + + it('throws if called with invalid arguments', () => { + const User = sequelize.define('User'); + + expect(() => { + queryGenerator.getWhereConditions(new Date(), User.getTableName(), User); + }).to.throw('Unsupported where option value'); + }); + + it('ignores undefined', () => { + const User = sequelize.define('User'); + + expect(queryGenerator.getWhereConditions(undefined, User.getTableName(), User)).to.eq(''); + }); + + it('ignores null', () => { + const User = sequelize.define('User'); + + expect(queryGenerator.getWhereConditions(null, User.getTableName(), User)).to.eq(''); + }); +}); diff --git a/test/unit/sql/group.test.js b/test/unit/sql/group.test.js index 2e51466bfc1c..a6d1407abd3a 100644 --- a/test/unit/sql/group.test.js +++ b/test/unit/sql/group.test.js @@ -41,6 +41,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'SELECT * FROM "Users" AS "User" GROUP BY "name";', db2: 'SELECT * FROM "Users" AS "User" GROUP BY "name";', mssql: 'SELECT * FROM [Users] AS [User] GROUP BY [name];', + oracle: 'SELECT * FROM "Users" "User" GROUP BY "name";', snowflake: 'SELECT * FROM "Users" AS "User" GROUP BY "name";' }); @@ -52,6 +53,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'SELECT * FROM "Users" AS "User";', db2: 'SELECT * FROM "Users" AS "User";', mssql: 'SELECT * FROM [Users] AS [User];', + oracle: 'SELECT * FROM "Users" "User";', snowflake: 'SELECT * FROM "Users" AS "User";' }); }); diff --git a/test/unit/sql/index.test.js b/test/unit/sql/index.test.js index 03371188ade7..8ebb7904677b 100644 --- a/test/unit/sql/index.test.js +++ b/test/unit/sql/index.test.js @@ -54,6 +54,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mssql: 'CREATE FULLTEXT INDEX [user_field_c] ON [User] ([fieldC])', postgres: 'CREATE INDEX CONCURRENTLY "user_field_c" ON "User" ("fieldC")', mariadb: 'ALTER TABLE `User` ADD FULLTEXT INDEX `user_field_c` (`fieldC`)', + oracle: 'CREATE INDEX "user_field_c" ON "User" ("fieldC")', mysql: 'ALTER TABLE `User` ADD FULLTEXT INDEX `user_field_c` (`fieldC`)' }); @@ -68,6 +69,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'CREATE UNIQUE INDEX "a_b_uniq" ON "User" ("fieldB", "fieldA" DESC)', postgres: 'CREATE UNIQUE INDEX "a_b_uniq" ON "User" USING BTREE ("fieldB", "fieldA" COLLATE "en_US" DESC)', mariadb: 'ALTER TABLE `User` ADD UNIQUE INDEX `a_b_uniq` USING BTREE (`fieldB`, `fieldA`(5) DESC) WITH PARSER foo', + oracle: 'CREATE UNIQUE INDEX "a_b_uniq" ON "User" ("fieldB", "fieldA" DESC)', mysql: 'ALTER TABLE `User` ADD UNIQUE INDEX `a_b_uniq` USING BTREE (`fieldB`, `fieldA`(5) DESC) WITH PARSER foo' }); }); @@ -78,6 +80,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mssql: 'CREATE INDEX [table_column] ON [table] ([column] DESC)', db2: 'CREATE INDEX "table_column" ON "table" ("column" DESC)', mariadb: 'ALTER TABLE `table` ADD INDEX `table_column` (`column`(5) DESC)', + oracle: 'CREATE INDEX "table_column" ON "table" ("column" DESC)', mysql: 'ALTER TABLE `table` ADD INDEX `table_column` (`column`(5) DESC)' }); }); @@ -250,6 +253,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: 'DROP INDEX `table_column1_column2` ON `table`', mssql: 'DROP INDEX [table_column1_column2] ON [table]', db2: 'DROP INDEX "table_column1_column2"', + oracle: 'DROP INDEX "table_column1_column2"', default: 'DROP INDEX IF EXISTS [table_column1_column2]' }); }); diff --git a/test/unit/sql/insert.test.js b/test/unit/sql/insert.test.js index ea5fe6e31576..8924fcdbaa02 100644 --- a/test/unit/sql/insert.test.js +++ b/test/unit/sql/insert.test.js @@ -32,7 +32,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'INSERT INTO "users" ("user_name") VALUES ($1) RETURNING "id","user_name";', db2: 'SELECT * FROM FINAL TABLE(INSERT INTO "users" ("user_name") VALUES ($1));', snowflake: 'INSERT INTO "users" ("user_name") VALUES ($1);', - default: 'INSERT INTO `users` (`user_name`) VALUES ($1);' + oracle: 'INSERT INTO "users" ("user_name") VALUES (:1) RETURNING "id","user_name" INTO :2,:3;', + default: 'INSERT INTO `users` (`user_name`) VALUES ($1);' }, bind: ['triggertest'] }); @@ -55,6 +56,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE(INSERT INTO "ms" ("id") VALUES ($1));', postgres: 'INSERT INTO "ms" ("id") VALUES ($1);', snowflake: 'INSERT INTO "ms" ("id") VALUES ($1);', + oracle: 'INSERT INTO "ms" ("id") VALUES (:1);', default: 'INSERT INTO `ms` (`id`) VALUES ($1);' }, bind: [0] @@ -62,6 +64,70 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }); }); + it( + current.dialect.supports.inserts.onConflictWhere + ? 'adds conflictWhere clause to generated queries' + : 'throws error if conflictWhere is provided', + () => { + const User = Support.sequelize.define( + 'user', + { + username: { + type: DataTypes.STRING, + field: 'user_name', + primaryKey: true + }, + password: { + type: DataTypes.STRING, + field: 'pass_word' + }, + createdAt: { + type: DataTypes.DATE, + field: 'created_at' + }, + updatedAt: { + type: DataTypes.DATE, + field: 'updated_at' + } + }, + { + timestamps: true + } + ); + + const upsertKeys = ['user_name']; + + let result; + + try { + result = sql.insertQuery( + User.tableName, + { user_name: 'testuser', pass_word: '12345' }, + User.fieldRawAttributesMap, + { + updateOnDuplicate: ['user_name', 'pass_word', 'updated_at'], + conflictWhere: { + user_name: 'test where value' + }, + upsertKeys + } + ); + } catch (error) { + result = error; + } + + expectsql(result, { + default: new Error( + 'missing dialect support for conflictWhere option' + ), + postgres: + 'INSERT INTO "users" ("user_name","pass_word") VALUES ($1,$2) ON CONFLICT ("user_name") WHERE "user_name" = \'test where value\' DO UPDATE SET "user_name"=EXCLUDED."user_name","pass_word"=EXCLUDED."pass_word","updated_at"=EXCLUDED."updated_at";', + sqlite: + 'INSERT INTO `users` (`user_name`,`pass_word`) VALUES ($1,$2) ON CONFLICT (`user_name`) WHERE `user_name` = \'test where value\' DO UPDATE SET `user_name`=EXCLUDED.`user_name`,`pass_word`=EXCLUDED.`pass_word`,`updated_at`=EXCLUDED.`updated_at`;' + }); + } + ); + describe('dates', () => { it('formats the date correctly when inserting', () => { const timezoneSequelize = Support.createSequelizeInstance({ @@ -82,6 +148,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'INSERT INTO "users" ("date") VALUES ($1);', db2: 'SELECT * FROM FINAL TABLE(INSERT INTO "users" ("date") VALUES ($1));', snowflake: 'INSERT INTO "users" ("date") VALUES ($1);', + oracle: 'INSERT INTO "users" ("date") VALUES (:1);', mssql: 'INSERT INTO [users] ([date]) VALUES ($1);', default: 'INSERT INTO `users` (`date`) VALUES ($1);' }, @@ -91,6 +158,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: ['2015-01-20 01:00:00'], snowflake: ['2015-01-20 01:00:00'], mariadb: ['2015-01-20 01:00:00.000'], + oracle: [new Date(Date.UTC(2015, 0, 20))], default: ['2015-01-20 01:00:00.000 +01:00'] } }); @@ -116,11 +184,13 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE(INSERT INTO "users" ("date") VALUES ($1));', snowflake: 'INSERT INTO "users" ("date") VALUES ($1);', mssql: 'INSERT INTO [users] ([date]) VALUES ($1);', + oracle: 'INSERT INTO "users" ("date") VALUES (:1);', default: 'INSERT INTO `users` (`date`) VALUES ($1);' }, bind: { sqlite: ['2015-01-20 01:02:03.089 +00:00'], mariadb: ['2015-01-20 02:02:03.089'], + oracle: [new Date(Date.UTC(2015, 0, 20, 1, 2, 3, 89))], mysql: ['2015-01-20 02:02:03.089'], db2: ['2015-01-20 02:02:03.089'], snowflake: ['2015-01-20 02:02:03.089'], @@ -148,6 +218,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'SELECT * FROM FINAL TABLE(INSERT INTO "users" ("user_name") VALUES ($1));', snowflake: 'INSERT INTO "users" ("user_name") VALUES ($1);', mssql: 'INSERT INTO [users] ([user_name]) VALUES ($1);', + oracle: 'INSERT INTO "users" ("user_name") VALUES (:1);', default: 'INSERT INTO `users` (`user_name`) VALUES ($1);' }, bind: { @@ -189,6 +260,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { { default: 'INSERT INTO `users` (`user_name`,`pass_word`) VALUES (\'testuser\',\'12345\');', snowflake: 'INSERT INTO "users" ("user_name","pass_word") VALUES (\'testuser\',\'12345\');', + oracle: 'INSERT INTO "users" ("user_name","pass_word") VALUES (:1,:2)', postgres: 'INSERT INTO "users" ("user_name","pass_word") VALUES (\'testuser\',\'12345\') ON CONFLICT ("user_name") DO UPDATE SET "user_name"=EXCLUDED."user_name","pass_word"=EXCLUDED."pass_word","updated_at"=EXCLUDED."updated_at";', mssql: 'INSERT INTO [users] ([user_name],[pass_word]) VALUES (N\'testuser\',N\'12345\');', db2: 'INSERT INTO "users" ("user_name","pass_word") VALUES (\'testuser\',\'12345\');', @@ -198,7 +270,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }); }); - it('allow bulk insert primary key with 0', () => { + // Oracle dialect doesn't support mix of null and non-null in auto-increment column + (current.dialect.name !== 'oracle' ? it : it.skip)('allow bulk insert primary key with 0', () => { const M = Support.sequelize.define('m', { id: { type: DataTypes.INTEGER, @@ -218,5 +291,71 @@ describe(Support.getTestDialectTeaser('SQL'), () => { } }); }); + + if ( + current.dialect.supports.inserts.updateOnDuplicate + ) { + it('correctly generates SQL for conflictWhere', () => { + const User = Support.sequelize.define( + 'user', + { + username: { + type: DataTypes.STRING, + field: 'user_name', + primaryKey: true + }, + password: { + type: DataTypes.STRING, + field: 'pass_word' + }, + createdAt: { + type: DataTypes.DATE, + field: 'created_at' + }, + updatedAt: { + type: DataTypes.DATE, + field: 'updated_at' + }, + deletedAt: { + type: DataTypes.DATE, + field: 'deleted_at' + } + }, + { + timestamps: true + } + ); + + // mapping primary keys to their "field" override values + const primaryKeys = User.primaryKeyAttributes.map(attr => User.getAttributes()[attr].field || attr); + + let result; + + try { + result = sql.bulkInsertQuery( + User.tableName, + [{ user_name: 'testuser', pass_word: '12345' }], + { + updateOnDuplicate: ['user_name', 'pass_word', 'updated_at'], + upsertKeys: primaryKeys, + conflictWhere: { deleted_at: null } + }, + User.fieldRawAttributesMap + ); + } catch (error) { + result = error; + } + + expectsql(result, { + default: new Error( + `conflictWhere not supported for dialect ${current.dialect.name}` + ), + 'postgres': + 'INSERT INTO "users" ("user_name","pass_word") VALUES (\'testuser\',\'12345\') ON CONFLICT ("user_name") WHERE "deleted_at" IS NULL DO UPDATE SET "user_name"=EXCLUDED."user_name","pass_word"=EXCLUDED."pass_word","updated_at"=EXCLUDED."updated_at";', + 'sqlite': + 'INSERT INTO `users` (`user_name`,`pass_word`) VALUES (\'testuser\',\'12345\') ON CONFLICT (`user_name`) WHERE `deleted_at` IS NULL DO UPDATE SET `user_name`=EXCLUDED.`user_name`,`pass_word`=EXCLUDED.`pass_word`,`updated_at`=EXCLUDED.`updated_at`;' + }); + }); + } }); }); diff --git a/test/unit/sql/json.test.js b/test/unit/sql/json.test.js index 1e874a411ad0..a1b8939c11d1 100644 --- a/test/unit/sql/json.test.js +++ b/test/unit/sql/json.test.js @@ -84,6 +84,7 @@ if (current.dialect.supports.JSON) { postgres: '("id"#>>\'{}\') = \'1\'', sqlite: "json_extract(`id`,'$') = '1'", mariadb: "json_unquote(json_extract(`id`,'$')) = '1'", + oracle: 'json_value("id",\'$\') = \'1\'', mysql: "json_unquote(json_extract(`id`,'$')) = '1'" }); }); @@ -93,6 +94,7 @@ if (current.dialect.supports.JSON) { postgres: '("profile"#>>\'{id}\') = \'1\'', sqlite: "json_extract(`profile`,'$.id') = '1'", mariadb: "json_unquote(json_extract(`profile`,'$.id')) = '1'", + oracle: 'json_value("profile",\'$."id"\') = \'1\'', mysql: "json_unquote(json_extract(`profile`,'$.\\\"id\\\"')) = '1'" }); }); @@ -102,6 +104,7 @@ if (current.dialect.supports.JSON) { postgres: '("property"#>>\'{value}\') = \'1\' AND ("another"#>>\'{value}\') = \'string\'', sqlite: "json_extract(`property`,'$.value') = '1' AND json_extract(`another`,'$.value') = 'string'", mariadb: "json_unquote(json_extract(`property`,'$.value')) = '1' AND json_unquote(json_extract(`another`,'$.value')) = 'string'", + oracle: 'json_value("property",\'$."value"\') = \'1\' AND json_value("another",\'$."value"\') = \'string\'', mysql: "json_unquote(json_extract(`property`,'$.\\\"value\\\"')) = '1' AND json_unquote(json_extract(`another`,'$.\\\"value\\\"')) = 'string'" }); }); @@ -111,6 +114,7 @@ if (current.dialect.supports.JSON) { postgres: '("property"#>>\'{0,0}\') = \'4\' AND ("property"#>>\'{0,1}\') = \'6\' AND ("property"#>>\'{1,0}\') = \'8\'', sqlite: "json_extract(`property`,'$[0][0]') = '4' AND json_extract(`property`,'$[0][1]') = '6' AND json_extract(`property`,'$[1][0]') = '8'", mariadb: "json_unquote(json_extract(`property`,'$[0][0]')) = '4' AND json_unquote(json_extract(`property`,'$[0][1]')) = '6' AND json_unquote(json_extract(`property`,'$[1][0]')) = '8'", + oracle: 'json_value("property",\'$[0][0]\') = \'4\' AND json_value("property",\'$[0][1]\') = \'6\' AND json_value("property",\'$[1][0]\') = \'8\'', mysql: "json_unquote(json_extract(`property`,'$[0][0]')) = '4' AND json_unquote(json_extract(`property`,'$[0][1]')) = '6' AND json_unquote(json_extract(`property`,'$[1][0]')) = '8'" }); }); @@ -120,6 +124,7 @@ if (current.dialect.supports.JSON) { postgres: '("profile"#>>\'{id}\') = \'1\'', sqlite: "json_extract(`profile`,'$.id') = '1'", mariadb: "json_unquote(json_extract(`profile`,'$.id')) = '1'", + oracle: 'json_value("profile",\'$."id"\') = \'1\'', mysql: "json_unquote(json_extract(`profile`,'$.\\\"id\\\"')) = '1'" }); }); @@ -129,6 +134,7 @@ if (current.dialect.supports.JSON) { postgres: '("profile"#>>\'{id,0,1}\') = \'1\'', sqlite: "json_extract(`profile`,'$.id[0][1]') = '1'", mariadb: "json_unquote(json_extract(`profile`,'$.id[0][1]')) = '1'", + oracle: 'json_value("profile",\'$."id"[0][1]\') = \'1\'', mysql: "json_unquote(json_extract(`profile`,'$.\\\"id\\\"[0][1]')) = '1'" }); }); @@ -138,6 +144,7 @@ if (current.dialect.supports.JSON) { postgres: '("json"#>>\'{}\') = \'{}\'', sqlite: "json_extract(`json`,'$') = '{}'", mariadb: "json_unquote(json_extract(`json`,'$')) = '{}'", + oracle: 'json_value("json",\'$\') = \'{}\'', mysql: "json_unquote(json_extract(`json`,'$')) = '{}'" }); }); @@ -159,7 +166,9 @@ if (current.dialect.supports.JSON) { }); it('nested json functions', () => { - expectsql(sql.handleSequelizeMethod(Sequelize.json('json_extract(json_object(\'{"profile":null}\'), "profile")')), { + const rawJSON = current.dialect.name === 'oracle' ? 'json_value(json_object(\'{"profile":null}\'), "profile")' : 'json_extract(json_object(\'{"profile":null}\'), "profile")'; + expectsql(sql.handleSequelizeMethod(Sequelize.json(rawJSON)), { + oracle: 'json_value(json_object(\'{"profile":null}\'), "profile")', default: 'json_extract(json_object(\'{"profile":null}\'), "profile")' }); }); @@ -180,6 +189,70 @@ if (current.dialect.supports.JSON) { expect(() => sql.handleSequelizeMethod(Sequelize.json('json(); DELETE YOLO INJECTIONS; -- '))).to.throw(); }); }); + + describe('cast type injection', () => { + const jsonFieldOptions = { field: { type: new DataTypes.JSON() } }; + + it('should reject SQL injection via :: cast type notation in JSON keys', () => { + expect(() => { + sql.whereItemQuery('data', { 'role::text) OR 1=1--': 'anything' }, jsonFieldOptions); + }).to.throw(Error, /Invalid cast type/); + }); + + it('should reject UNION-based injection via :: cast type notation', () => { + expect(() => { + sql.whereItemQuery('data', { 'role::text) AND 0 UNION SELECT * FROM secrets--': 'x' }, jsonFieldOptions); + }).to.throw(Error, /Invalid cast type/); + }); + + it('should allow valid cast types via :: notation', () => { + expect(() => { + sql.whereItemQuery('data', { 'id::integer': 1 }, jsonFieldOptions); + }).to.not.throw(); + }); + + it('should allow the text cast type via :: notation', () => { + expect(() => { + sql.whereItemQuery('data', { 'name::text': 'value' }, jsonFieldOptions); + }).to.not.throw(); + }); + + it('should reject cast types with parentheses', () => { + expect(() => { + sql.whereItemQuery('data', { 'role::text)': 'anything' }, jsonFieldOptions); + }).to.throw(Error, /Invalid cast type/); + }); + + it('should reject cast types with semicolons', () => { + expect(() => { + sql.whereItemQuery('data', { 'role::text; DROP TABLE users': 'anything' }, jsonFieldOptions); + }).to.throw(Error, /Invalid cast type/); + }); + + it('should reject cast types with comment markers', () => { + expect(() => { + sql.whereItemQuery('data', { 'role::text--': 'anything' }, jsonFieldOptions); + }).to.throw(Error, /Invalid cast type/); + }); + + it('should allow double precision cast type', () => { + expect(() => { + sql.whereItemQuery('data', { 'level::double precision': 1 }, jsonFieldOptions); + }).to.not.throw(); + }); + + it('should reject empty cast type', () => { + expect(() => { + sql.whereItemQuery('data', { 'role::': 'anything' }, jsonFieldOptions); + }).to.throw(Error, /Invalid cast type/); + }); + + it('should reject unknown cast types', () => { + expect(() => { + sql.whereItemQuery('data', { 'role::foobar': 'anything' }, jsonFieldOptions); + }).to.throw(Error, /Invalid cast type/); + }); + }); }); }); } diff --git a/test/unit/sql/offset-limit.test.js b/test/unit/sql/offset-limit.test.js index a81238eb6254..04db33ab4441 100644 --- a/test/unit/sql/offset-limit.test.js +++ b/test/unit/sql/offset-limit.test.js @@ -30,6 +30,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, { default: ' LIMIT 10', db2: ' FETCH NEXT 10 ROWS ONLY', + oracle: ' ORDER BY "tableRef"."id" OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY', mssql: ' ORDER BY [tableRef].[id] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY' }); @@ -41,6 +42,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, { default: ' LIMIT 10', db2: ' FETCH NEXT 10 ROWS ONLY', + oracle: ' OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY', mssql: ' OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY' }); @@ -55,6 +57,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { snowflake: ' LIMIT 10 OFFSET 20', postgres: ' LIMIT 10 OFFSET 20', db2: ' OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY', + oracle: ' OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY', mssql: ' OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY' }); @@ -69,6 +72,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { snowflake: " LIMIT ''';DELETE FROM user'", mysql: " LIMIT '\\';DELETE FROM user'", db2: " FETCH NEXT ''';DELETE FROM user' ROWS ONLY", + oracle: " OFFSET 0 ROWS FETCH NEXT ''';DELETE FROM user' ROWS ONLY", mssql: " OFFSET 0 ROWS FETCH NEXT N''';DELETE FROM user' ROWS ONLY" }); @@ -85,6 +89,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { snowflake: " LIMIT 10 OFFSET ''';DELETE FROM user'", mysql: " LIMIT '\\';DELETE FROM user', 10", db2: ' FETCH NEXT 10 ROWS ONLY', + oracle: " OFFSET ''';DELETE FROM user' ROWS FETCH NEXT 10 ROWS ONLY", mssql: " OFFSET N''';DELETE FROM user' ROWS FETCH NEXT 10 ROWS ONLY" }); @@ -95,6 +100,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, { db2: ' FETCH NEXT 10 ROWS ONLY', default: ' LIMIT 10', + oracle: ' ORDER BY "tableRef"."id" OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY', mssql: ' ORDER BY [tableRef].[id] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY' }); }); diff --git a/test/unit/sql/order.test.js b/test/unit/sql/order.test.js index 3f399a3ad566..e3beee45fa84 100644 --- a/test/unit/sql/order.test.js +++ b/test/unit/sql/order.test.js @@ -341,6 +341,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ] }, { default: 'SELECT [Subtask].[id], [Subtask].[name], [Subtask].[createdAt], [Task].[id] AS [Task.id], [Task].[name] AS [Task.name], [Task].[created_at] AS [Task.createdAt], [Task->Project].[id] AS [Task.Project.id], [Task->Project].[name] AS [Task.Project.name], [Task->Project].[created_at] AS [Task.Project.createdAt] FROM [subtask] AS [Subtask] INNER JOIN [task] AS [Task] ON [Subtask].[task_id] = [Task].[id] INNER JOIN [project] AS [Task->Project] ON [Task].[project_id] = [Task->Project].[id] ORDER BY [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Task->Project].[created_at] ASC, [Task->Project].[created_at], [Task].[created_at] ASC, [Task].[created_at], [Subtask].[created_at] ASC, [Subtask].[created_at], [Subtask].[created_at];', + oracle: 'SELECT "Subtask"."id", "Subtask"."name", "Subtask"."createdAt", "Task"."id" AS "Task.id", "Task"."name" AS "Task.name", "Task"."created_at" AS "Task.createdAt", "Task->Project"."id" AS "Task.Project.id", "Task->Project"."name" AS "Task.Project.name", "Task->Project"."created_at" AS "Task.Project.createdAt" FROM "subtask" "Subtask" INNER JOIN "task" "Task" ON "Subtask"."task_id" = "Task"."id" INNER JOIN "project" "Task->Project" ON "Task"."project_id" = "Task->Project"."id" ORDER BY "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Subtask"."created_at" ASC, "Subtask"."created_at", "Subtask"."created_at";', postgres: 'SELECT "Subtask"."id", "Subtask"."name", "Subtask"."createdAt", "Task"."id" AS "Task.id", "Task"."name" AS "Task.name", "Task"."created_at" AS "Task.createdAt", "Task->Project"."id" AS "Task.Project.id", "Task->Project"."name" AS "Task.Project.name", "Task->Project"."created_at" AS "Task.Project.createdAt" FROM "subtask" AS "Subtask" INNER JOIN "task" AS "Task" ON "Subtask"."task_id" = "Task"."id" INNER JOIN "project" AS "Task->Project" ON "Task"."project_id" = "Task->Project"."id" ORDER BY "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Task->Project"."created_at" ASC, "Task->Project"."created_at", "Task"."created_at" ASC, "Task"."created_at", "Subtask"."created_at" ASC, "Subtask"."created_at", "Subtask"."created_at";' }); @@ -357,6 +358,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: 'SELECT `id`, `name` FROM `subtask` AS `Subtask` ORDER BY RAND();', postgres: 'SELECT "id", "name" FROM "subtask" AS "Subtask" ORDER BY RANDOM();', snowflake: 'SELECT "id", "name" FROM "subtask" AS "Subtask" ORDER BY RANDOM();', + oracle: 'SELECT "id", "name" FROM "subtask" "Subtask" ORDER BY RAND();', sqlite: 'SELECT `id`, `name` FROM `subtask` AS `Subtask` ORDER BY RANDOM();' }); diff --git a/test/unit/sql/remove-column.test.js b/test/unit/sql/remove-column.test.js index fc4f3fa6ee52..11c352ce36f2 100644 --- a/test/unit/sql/remove-column.test.js +++ b/test/unit/sql/remove-column.test.js @@ -1,15 +1,21 @@ 'use strict'; -const Support = require('../support'), - expectsql = Support.expectsql, - current = Support.sequelize, - sql = current.dialect.queryGenerator; +const Support = require('../support'); + +const expectsql = Support.expectsql; +const current = Support.sequelize; +const sql = current.dialect.queryGenerator; + +const customSequelize = Support.createSequelizeInstance({ + schema: 'custom' +}); +const customSql = customSequelize.dialect.queryGenerator; // Notice: [] will be replaced by dialect specific tick/quote character when there is not dialect specific expectation but only a default expectation -if (current.dialect.name !== 'sqlite') { - describe(Support.getTestDialectTeaser('SQL'), () => { - describe('removeColumn', () => { +describe(Support.getTestDialectTeaser('SQL'), () => { + describe('removeColumn', () => { + if (current.dialect.name !== 'sqlite') { it('schema', () => { expectsql(sql.removeColumnQuery({ schema: 'archive', @@ -20,9 +26,25 @@ if (current.dialect.name !== 'sqlite') { mariadb: 'ALTER TABLE `archive`.`user` DROP `email`;', mysql: 'ALTER TABLE `archive.user` DROP `email`;', postgres: 'ALTER TABLE "archive"."user" DROP COLUMN "email";', - snowflake: 'ALTER TABLE "archive"."user" DROP "email";' + snowflake: 'ALTER TABLE "archive"."user" DROP "email";', + oracle: 'ALTER TABLE "archive"."user" DROP COLUMN "email";' }); }); + } + + it('defaults the schema to the one set in the Sequelize options', () => { + expectsql(customSql.removeColumnQuery({ + tableName: 'user' + }, 'email'), { + mssql: 'ALTER TABLE [user] DROP COLUMN [email];', + db2: 'ALTER TABLE "user" DROP COLUMN "email";', + mariadb: 'ALTER TABLE `user` DROP `email`;', + mysql: 'ALTER TABLE `user` DROP `email`;', + postgres: 'ALTER TABLE "custom"."user" DROP COLUMN "email";', + snowflake: 'ALTER TABLE "user" DROP "email";', + sqlite: 'CREATE TABLE IF NOT EXISTS `user_backup` (`0` e, `1` m, `2` a, `3` i, `4` l);INSERT INTO `user_backup` SELECT `0`, `1`, `2`, `3`, `4` FROM `user`;DROP TABLE `user`;CREATE TABLE IF NOT EXISTS `user` (`0` e, `1` m, `2` a, `3` i, `4` l);INSERT INTO `user` SELECT `0`, `1`, `2`, `3`, `4` FROM `user_backup`;DROP TABLE `user_backup`;', + oracle: 'ALTER TABLE "user" DROP COLUMN "email";' + }); }); }); -} +}); diff --git a/test/unit/sql/select.test.js b/test/unit/sql/select.test.js index 544d8d5cf6be..008a2b38665a 100644 --- a/test/unit/sql/select.test.js +++ b/test/unit/sql/select.test.js @@ -48,6 +48,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, { default: "SELECT [email], [first_name] AS [firstName] FROM [User] WHERE [User].[email] = 'jon.snow@gmail.com' ORDER BY [email] DESC LIMIT 10;", db2: 'SELECT "email", "first_name" AS "firstName" FROM "User" WHERE "User"."email" = \'jon.snow@gmail.com\' ORDER BY "email" DESC FETCH NEXT 10 ROWS ONLY;', + oracle: 'SELECT "email", "first_name" AS "firstName" FROM "User" WHERE "User"."email" = \'jon.snow@gmail.com\' ORDER BY "email" DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;', mssql: "SELECT [email], [first_name] AS [firstName] FROM [User] WHERE [User].[email] = N'jon.snow@gmail.com' ORDER BY [email] DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;" }); @@ -70,6 +71,12 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ] } }, { + oracle: `SELECT "User".* FROM (${ + [ + `SELECT * FROM (SELECT "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "User" WHERE "User"."companyId" = 1 ORDER BY "last_name" ASC${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) sub`, + `SELECT * FROM (SELECT "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "User" WHERE "User"."companyId" = 5 ORDER BY "last_name" ASC${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) sub` + ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ') + }) "User" ORDER BY "last_name" ASC;`, default: `SELECT [User].* FROM (${ [ `SELECT * FROM (SELECT [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [User] WHERE [User].[companyId] = 1 ORDER BY [last_name] ASC${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub`, @@ -128,7 +135,11 @@ describe(Support.getTestDialectTeaser('SQL'), () => { `SELECT * FROM (SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_users].[user_id] AS [project_users.userId], [project_users].[project_id] AS [project_users.projectId] FROM [users] AS [user] INNER JOIN [project_users] AS [project_users] ON [user].[id_user] = [project_users].[user_id] AND [project_users].[project_id] = 1 ORDER BY [subquery_order_0] ASC${ current.dialect.name === 'mssql' ? ', [user].[id_user]' : ''}${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub`, `SELECT * FROM (SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_users].[user_id] AS [project_users.userId], [project_users].[project_id] AS [project_users.projectId] FROM [users] AS [user] INNER JOIN [project_users] AS [project_users] ON [user].[id_user] = [project_users].[user_id] AND [project_users].[project_id] = 5 ORDER BY [subquery_order_0] ASC${ current.dialect.name === 'mssql' ? ', [user].[id_user]' : ''}${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub` ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ') - }) AS [user] ORDER BY [subquery_order_0] ASC;` + }) AS [user] ORDER BY [subquery_order_0] ASC;`, + oracle: 'SELECT "user".* FROM (' + + 'SELECT * FROM (SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_users"."user_id" AS "project_users.userId", "project_users"."project_id" AS "project_users.projectId" FROM "users" "user" INNER JOIN "project_users" "project_users" ON "user"."id_user" = "project_users"."user_id" AND "project_users"."project_id" = 1 ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub UNION ALL ' + + 'SELECT * FROM (SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_users"."user_id" AS "project_users.userId", "project_users"."project_id" AS "project_users.projectId" FROM "users" "user" INNER JOIN "project_users" "project_users" ON "user"."id_user" = "project_users"."user_id" AND "project_users"."project_id" = 5 ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub)' + + ' "user" ORDER BY "subquery_order_0" ASC;' }); testsql({ @@ -159,7 +170,11 @@ describe(Support.getTestDialectTeaser('SQL'), () => { `SELECT * FROM (SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_users].[user_id] AS [project_users.userId], [project_users].[project_id] AS [project_users.projectId] FROM [users] AS [user] INNER JOIN [project_users] AS [project_users] ON [user].[id_user] = [project_users].[user_id] AND [project_users].[project_id] = 1 AND [project_users].[status] = 1 ORDER BY [subquery_order_0] ASC${ current.dialect.name === 'mssql' ? ', [user].[id_user]' : ''}${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub`, `SELECT * FROM (SELECT [user].[id_user] AS [id], [user].[last_name] AS [subquery_order_0], [project_users].[user_id] AS [project_users.userId], [project_users].[project_id] AS [project_users.projectId] FROM [users] AS [user] INNER JOIN [project_users] AS [project_users] ON [user].[id_user] = [project_users].[user_id] AND [project_users].[project_id] = 5 AND [project_users].[status] = 1 ORDER BY [subquery_order_0] ASC${ current.dialect.name === 'mssql' ? ', [user].[id_user]' : ''}${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub` ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ') - }) AS [user] ORDER BY [subquery_order_0] ASC;` + }) AS [user] ORDER BY [subquery_order_0] ASC;`, + oracle: 'SELECT "user".* FROM (' + + 'SELECT * FROM (SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_users"."user_id" AS "project_users.userId", "project_users"."project_id" AS "project_users.projectId" FROM "users" "user" INNER JOIN "project_users" "project_users" ON "user"."id_user" = "project_users"."user_id" AND "project_users"."project_id" = 1 AND "project_users"."status" = 1 ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub UNION ALL ' + + 'SELECT * FROM (SELECT "user"."id_user" AS "id", "user"."last_name" AS "subquery_order_0", "project_users"."user_id" AS "project_users.userId", "project_users"."project_id" AS "project_users.projectId" FROM "users" "user" INNER JOIN "project_users" "project_users" ON "user"."id_user" = "project_users"."user_id" AND "project_users"."project_id" = 5 AND "project_users"."status" = 1 ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub)' + + ' "user" ORDER BY "subquery_order_0" ASC;' }); testsql({ @@ -190,7 +205,12 @@ describe(Support.getTestDialectTeaser('SQL'), () => { `SELECT * FROM (SELECT [user].[id_user] AS [id], [user].[id_user] AS [subquery_order_0], [project_users].[user_id] AS [project_users.userId], [project_users].[project_id] AS [project_users.projectId] FROM [users] AS [user] INNER JOIN [project_users] AS [project_users] ON [user].[id_user] = [project_users].[user_id] AND [project_users].[project_id] = 1 WHERE [user].[age] >= 21 ORDER BY [subquery_order_0] ASC${ current.dialect.name === 'mssql' ? ', [user].[id_user]' : ''}${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub`, `SELECT * FROM (SELECT [user].[id_user] AS [id], [user].[id_user] AS [subquery_order_0], [project_users].[user_id] AS [project_users.userId], [project_users].[project_id] AS [project_users.projectId] FROM [users] AS [user] INNER JOIN [project_users] AS [project_users] ON [user].[id_user] = [project_users].[user_id] AND [project_users].[project_id] = 5 WHERE [user].[age] >= 21 ORDER BY [subquery_order_0] ASC${ current.dialect.name === 'mssql' ? ', [user].[id_user]' : ''}${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub` ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ') - }) AS [user] ORDER BY [subquery_order_0] ASC;` + }) AS [user] ORDER BY [subquery_order_0] ASC;`, + oracle: 'SELECT "user".* FROM (' + + 'SELECT * FROM (SELECT "user"."id_user" AS "id", "user"."id_user" AS "subquery_order_0", "project_users"."user_id" AS "project_users.userId", "project_users"."project_id" AS "project_users.projectId" FROM "users" "user" INNER JOIN "project_users" "project_users" ON "user"."id_user" = "project_users"."user_id" AND "project_users"."project_id" = 1 WHERE "user"."age" >= 21 ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub UNION ALL ' + + 'SELECT * FROM (SELECT "user"."id_user" AS "id", "user"."id_user" AS "subquery_order_0", "project_users"."user_id" AS "project_users.userId", "project_users"."project_id" AS "project_users.projectId" FROM "users" "user" INNER JOIN "project_users" "project_users" ON "user"."id_user" = "project_users"."user_id" AND "project_users"."project_id" = 5 WHERE "user"."age" >= 21 ORDER BY "subquery_order_0" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub) ' + + '"user" ORDER BY "subquery_order_0" ASC;' + }); }()); @@ -271,10 +291,14 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ] } }, { + oracle: 'SELECT "user".*, "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title" FROM (' + + 'SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 1 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub UNION ALL ' + + 'SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 5 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub) ' + + '"user" LEFT OUTER JOIN "post" "POSTS" ON "user"."id" = "POSTS"."user_id" ORDER BY "lastName" ASC;', default: `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (${ [ - `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 1 ORDER BY [user].[last_name] ASC${sql.addLimitAndOffset({ limit: 3, order: [['last_name', 'ASC']] })}) AS sub`, - `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 5 ORDER BY [user].[last_name] ASC${sql.addLimitAndOffset({ limit: 3, order: [['last_name', 'ASC']] })}) AS sub` + `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 1 ORDER BY [lastName] ASC${sql.addLimitAndOffset({ limit: 3, order: [['last_name', 'ASC']] })}) AS sub`, + `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 5 ORDER BY [lastName] ASC${sql.addLimitAndOffset({ limit: 3, order: [['last_name', 'ASC']] })}) AS sub` ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ') }) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id];` }); @@ -295,6 +319,9 @@ describe(Support.getTestDialectTeaser('SQL'), () => { hasMultiAssociation: true, //must be set only for mssql dialect here subQuery: true }, { + oracle: 'SELECT "user".*, "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title" FROM (' + + 'SELECT "user"."id_user" AS "id", "user"."email", "user"."first_name" AS "firstName", "user"."last_name" AS "lastName" FROM "users" "user" ORDER BY "user"."last_name" ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY)' + + ' "user" LEFT OUTER JOIN "post" "POSTS" ON "user"."id_user" = "POSTS"."user_id" ORDER BY "user"."last_name" ASC;', default: `${'SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM (' + 'SELECT [user].[id_user] AS [id], [user].[email], [user].[first_name] AS [firstName], [user].[last_name] AS [lastName] FROM [users] AS [user] ORDER BY [user].[last_name] ASC'}${ sql.addLimitAndOffset({ limit: 30, offset: 10, order: [['`user`.`last_name`', 'ASC']] }) @@ -319,6 +346,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { hasMultiAssociation: true, // must be set only for mssql dialect here subQuery: false }, { + oracle: 'SELECT "user"."id_user" AS "id", "user"."email", "user"."first_name" AS "firstName", "user"."last_name" AS "lastName", "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title" FROM "users" "user" LEFT OUTER JOIN "post" "POSTS" ON "user"."id_user" = "POSTS"."user_id" ORDER BY "user"."last_name" ASC OFFSET 10 ROWS FETCH NEXT 30 ROWS ONLY;', default: Support.minifySql(`SELECT [user].[id_user] AS [id], [user].[email], [user].[first_name] AS [firstName], [user].[last_name] AS [lastName], [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title] FROM [users] AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id_user] = [POSTS].[user_id] @@ -361,10 +389,14 @@ describe(Support.getTestDialectTeaser('SQL'), () => { ] } }, { + oracle: 'SELECT "user".*, "POSTS"."id" AS "POSTS.id", "POSTS"."title" AS "POSTS.title", "POSTS->COMMENTS"."id" AS "POSTS.COMMENTS.id", "POSTS->COMMENTS"."title" AS "POSTS.COMMENTS.title" FROM (' + + 'SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 1 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub UNION ALL ' + + 'SELECT * FROM (SELECT "id_user" AS "id", "email", "first_name" AS "firstName", "last_name" AS "lastName" FROM "users" "user" WHERE "user"."companyId" = 5 ORDER BY "lastName" ASC OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY) sub)' + + ' "user" LEFT OUTER JOIN "post" "POSTS" ON "user"."id" = "POSTS"."user_id" LEFT OUTER JOIN "comment" "POSTS->COMMENTS" ON "POSTS"."id" = "POSTS->COMMENTS"."post_id" ORDER BY "lastName" ASC;', default: `SELECT [user].*, [POSTS].[id] AS [POSTS.id], [POSTS].[title] AS [POSTS.title], [POSTS->COMMENTS].[id] AS [POSTS.COMMENTS.id], [POSTS->COMMENTS].[title] AS [POSTS.COMMENTS.title] FROM (${ [ - `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 1 ORDER BY [user].[last_name] ASC${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub`, - `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 5 ORDER BY [user].[last_name] ASC${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub` + `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 1 ORDER BY [lastName] ASC${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub`, + `SELECT * FROM (SELECT [id_user] AS [id], [email], [first_name] AS [firstName], [last_name] AS [lastName] FROM [users] AS [user] WHERE [user].[companyId] = 5 ORDER BY [lastName] ASC${sql.addLimitAndOffset({ limit: 3, order: ['last_name', 'ASC'] })}) AS sub` ].join(current.dialect.supports['UNION ALL'] ? ' UNION ALL ' : ' UNION ') }) AS [user] LEFT OUTER JOIN [post] AS [POSTS] ON [user].[id] = [POSTS].[user_id] LEFT OUTER JOIN [comment] AS [POSTS->COMMENTS] ON [POSTS].[id] = [POSTS->COMMENTS].[post_id];` }); @@ -398,6 +430,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }).include, model: User }, User), { + oracle: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."title" AS "Posts.title" FROM "User" "User" LEFT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";', default: 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[title] AS [Posts.title] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];' }); }); @@ -431,6 +464,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }).include, model: User }, User), { + oracle: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."title" AS "Posts.title" FROM "User" "User" RIGHT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";', default: `SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[title] AS [Posts.title] FROM [User] AS [User] ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];` }); }); @@ -473,7 +507,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }).include, model: User }, User), { - default: `SELECT [user].[id_user], [user].[id], [projects].[id] AS [projects.id], [projects].[title] AS [projects.title], [projects].[createdAt] AS [projects.createdAt], [projects].[updatedAt] AS [projects.updatedAt], [projects->project_user].[user_id] AS [projects.project_user.userId], [projects->project_user].[project_id] AS [projects.project_user.projectId] FROM [User] AS [user] ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN ( [project_users] AS [projects->project_user] INNER JOIN [projects] AS [projects] ON [projects].[id] = [projects->project_user].[project_id]) ON [user].[id_user] = [projects->project_user].[user_id];` + default: `SELECT [user].[id_user], [user].[id], [projects].[id] AS [projects.id], [projects].[title] AS [projects.title], [projects].[createdAt] AS [projects.createdAt], [projects].[updatedAt] AS [projects.updatedAt], [projects->project_user].[user_id] AS [projects.project_user.userId], [projects->project_user].[project_id] AS [projects.project_user.projectId] FROM [User] AS [user] ${current.dialect.supports['RIGHT JOIN'] ? 'RIGHT' : 'LEFT'} OUTER JOIN ( [project_users] AS [projects->project_user] INNER JOIN [projects] AS [projects] ON [projects].[id] = [projects->project_user].[project_id]) ON [user].[id_user] = [projects->project_user].[user_id];`, + oracle: 'SELECT "user"."id_user", "user"."id", "projects"."id" AS "projects.id", "projects"."title" AS "projects.title", "projects"."createdAt" AS "projects.createdAt", "projects"."updatedAt" AS "projects.updatedAt", "projects->project_user"."user_id" AS "projects.project_user.userId", "projects->project_user"."project_id" AS "projects.project_user.projectId" FROM "User" "user" RIGHT OUTER JOIN ( "project_users" "projects->project_user" INNER JOIN "projects" "projects" ON "projects"."id" = "projects->project_user"."project_id") ON "user"."id_user" = "projects->project_user"."user_id";' }); }); @@ -510,6 +545,9 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }).include, subQuery: true }, User), { + oracle: 'SELECT "User".* FROM ' + + '(SELECT "User"."name", "User"."age", "User"."id" AS "id", "postaliasname"."id" AS "postaliasname.id", "postaliasname"."title" AS "postaliasname.title" FROM "User" "User" ' + + 'INNER JOIN "Post" "postaliasname" ON "User"."id" = "postaliasname"."user_id" WHERE ( SELECT "user_id" FROM "Post" "postaliasname" WHERE ("postaliasname"."user_id" = "User"."id") ORDER BY "postaliasname"."id" OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY ) IS NOT NULL) "User";', default: 'SELECT [User].* FROM ' + '(SELECT [User].[name], [User].[age], [User].[id] AS [id], [postaliasname].[id] AS [postaliasname.id], [postaliasname].[title] AS [postaliasname.title] FROM [User] AS [User] ' + 'INNER JOIN [Post] AS [postaliasname] ON [User].[id] = [postaliasname].[user_id] ' + @@ -534,6 +572,10 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }).include, subQuery: true }, User), { + oracle: 'SELECT "User".* FROM ' + + '(SELECT "User"."name", "User"."age", "User"."id" AS "id", "postaliasname"."id" AS "postaliasname.id", "postaliasname"."title" AS "postaliasname.title" FROM "User" "User" ' + + 'INNER JOIN "Post" "postaliasname" ON "User"."id" = "postaliasname"."user_id" WHERE "postaliasname"."title" = \'test\' AND ( SELECT "user_id" FROM "Post" "postaliasname" ' + + 'WHERE ("postaliasname"."user_id" = "User"."id") ORDER BY "postaliasname"."id" OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY ) IS NOT NULL) "User";', default: 'SELECT [User].* FROM ' + '(SELECT [User].[name], [User].[age], [User].[id] AS [id], [postaliasname].[id] AS [postaliasname.id], [postaliasname].[title] AS [postaliasname.title] FROM [User] AS [User] ' + 'INNER JOIN [Post] AS [postaliasname] ON [User].[id] = [postaliasname].[user_id] ' + @@ -586,6 +628,15 @@ describe(Support.getTestDialectTeaser('SQL'), () => { offset: 0, subQuery: true }, Company), { + oracle: 'SELECT "Company".* FROM (' + + 'SELECT "Company"."name", "Company"."public", "Company"."id" AS "id" FROM "Company" "Company" ' + + 'INNER JOIN "Users" "Users" ON "Company"."id" = "Users"."companyId" ' + + 'INNER JOIN "Professions" "Users->Profession" ON "Users"."professionId" = "Users->Profession"."id" ' + + 'WHERE ("Company"."scopeId" IN (42)) AND "Users->Profession"."name" = \'test\' AND ( ' + + 'SELECT "Users"."companyId" FROM "Users" "Users" ' + + 'INNER JOIN "Professions" "Profession" ON "Users"."professionId" = "Profession"."id" ' + + 'WHERE ("Users"."companyId" = "Company"."id") ORDER BY "Users"."id" OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY ) ' + + 'IS NOT NULL ORDER BY "Company"."id" OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY) "Company";', default: 'SELECT [Company].* FROM (' + 'SELECT [Company].[name], [Company].[public], [Company].[id] AS [id] FROM [Company] AS [Company] ' + 'INNER JOIN [Users] AS [Users] ON [Company].[id] = [Users].[companyId] ' + @@ -619,6 +670,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: 'SELECT `name`, `age`, `data` FROM `User` AS `User` WHERE `User`.`data` IN (X\'313233\');', sqlite: 'SELECT `name`, `age`, `data` FROM `User` AS `User` WHERE `User`.`data` IN (X\'313233\');', db2: "SELECT \"name\", \"age\", \"data\" FROM \"User\" AS \"User\" WHERE \"User\".\"data\" IN ('x''313233''');", + oracle: 'SELECT "name", "age", "data" FROM "User" "User" WHERE "User"."data" IN (\'313233\');', mssql: 'SELECT [name], [age], [data] FROM [User] AS [User] WHERE [User].[data] IN (0x313233);' }); }); @@ -718,7 +770,8 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }).include, model: User }, User), { - default: 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM User; DELETE FROM User;SELECT id] AS [Posts.* FROM User; DELETE FROM User;SELECT id] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];' + default: 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM User; DELETE FROM User;SELECT id] AS [Posts.* FROM User; DELETE FROM User;SELECT id] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];', + oracle: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM User; DELETE FROM User;SELECT id" AS "Posts.* FROM User; DELETE FROM User;SELECT id" FROM "User" "User" LEFT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";' }); expectsql(sql.selectQuery('User', { @@ -734,6 +787,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }).include, model: User }, User), { + oracle: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM User; DELETE FROM User;SELECT id" AS "Posts.data" FROM "User" "User" LEFT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";', default: 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM User; DELETE FROM User;SELECT id] AS [Posts.data] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];' }); @@ -750,6 +804,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }).include, model: User }, User), { + oracle: 'SELECT "User"."name", "User"."age", "Posts"."id" AS "Posts.id", "Posts"."* FROM User; DELETE FROM User;SELECT id" AS "Posts.data" FROM "User" "User" LEFT OUTER JOIN "Post" "Posts" ON "User"."id" = "Posts"."user_id";', default: 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[* FROM User; DELETE FROM User;SELECT id] AS [Posts.data] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];' }); }); @@ -768,6 +823,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { expectsql(sql.selectQuery('User'), { default: 'SELECT * FROM [User];', postgres: 'SELECT * FROM "User";', + oracle: 'SELECT * FROM "User";', snowflake: 'SELECT * FROM User;' }); }); @@ -778,6 +834,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }), { default: 'SELECT [name], [age] FROM [User];', postgres: 'SELECT name, age FROM "User";', + oracle: 'SELECT name, age FROM "User";', snowflake: 'SELECT name, age FROM User;' }); }); @@ -812,6 +869,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, User), { default: 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[title] AS [Posts.title] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];', postgres: 'SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id;', + oracle: 'SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM "User" "User" LEFT OUTER JOIN Post Posts ON "User".id = Posts.user_id;', snowflake: 'SELECT User.name, User.age, Posts.id AS "Posts.id", Posts.title AS "Posts.title" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id;' }); }); @@ -859,6 +917,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, User), { default: 'SELECT [User].[name], [User].[age], [Posts].[id] AS [Posts.id], [Posts].[title] AS [Posts.title], [Posts->Comments].[id] AS [Posts.Comments.id], [Posts->Comments].[title] AS [Posts.Comments.title], [Posts->Comments].[createdAt] AS [Posts.Comments.createdAt], [Posts->Comments].[updatedAt] AS [Posts.Comments.updatedAt], [Posts->Comments].[post_id] AS [Posts.Comments.post_id] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id] LEFT OUTER JOIN [Comment] AS [Posts->Comments] ON [Posts].[id] = [Posts->Comments].[post_id];', postgres: 'SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id LEFT OUTER JOIN Comment AS "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;', + oracle: 'SELECT "User".name, "User".age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM "User" "User" LEFT OUTER JOIN Post Posts ON "User".id = Posts.user_id LEFT OUTER JOIN "Comment" "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;', snowflake: 'SELECT User.name, User.age, Posts.id AS "Posts.id", Posts.title AS "Posts.title", "Posts->Comments".id AS "Posts.Comments.id", "Posts->Comments".title AS "Posts.Comments.title", "Posts->Comments".createdAt AS "Posts.Comments.createdAt", "Posts->Comments".updatedAt AS "Posts.Comments.updatedAt", "Posts->Comments".post_id AS "Posts.Comments.post_id" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id LEFT OUTER JOIN Comment AS "Posts->Comments" ON Posts.id = "Posts->Comments".post_id;' }); }); @@ -896,6 +955,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, User), { default: 'SELECT [User].[name], [User].[age], [User].[status.label], [Posts].[id] AS [Posts.id], [Posts].[title] AS [Posts.title], [Posts].[status.label] AS [Posts.status.label] FROM [User] AS [User] LEFT OUTER JOIN [Post] AS [Posts] ON [User].[id] = [Posts].[user_id];', postgres: 'SELECT "User".name, "User".age, "User"."status.label", Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.status.label" FROM "User" AS "User" LEFT OUTER JOIN Post AS Posts ON "User".id = Posts.user_id;', + oracle: 'SELECT "User".name, "User".age, "User"."status.label", Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.status.label" FROM "User" "User" LEFT OUTER JOIN Post Posts ON "User".id = Posts.user_id;', snowflake: 'SELECT User.name, User.age, User."status.label", Posts.id AS "Posts.id", Posts.title AS "Posts.title", Posts."status.label" AS "Posts.status.label" FROM User AS User LEFT OUTER JOIN Post AS Posts ON User.id = Posts.user_id;' }); }); @@ -957,4 +1017,105 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }).to.throw(Error, 'Support for `{where: \'raw query\'}` has been removed.'); }); }); + + + describe('queryGenerator: selectQuery', () => { + const User = Support.sequelize.define('User', { + username: DataTypes.STRING + }, { timestamps: false }); + + + const Project = Support.sequelize.define('Project', { + duration: DataTypes.BIGINT + }, { timestamps: false }); + + const ProjectContributor = Support.sequelize.define('ProjectContributor', {}, { timestamps: false }); + + // project owners + User.hasMany(Project, { as: 'projects' }); + Project.belongsTo(User, { as: 'owner' }); + + // project contributors + Project.belongsToMany(User, { + through: ProjectContributor, + as: 'contributors' + }); + + it('supports offset without limit', () => { + const query = sql.selectQuery(User.tableName, { + model: User, + attributes: ['id'], + offset: 1 + }, User); + + expectsql(query, { + postgres: 'SELECT "id" FROM "Users" AS "User" OFFSET 1;', + mysql: 'SELECT `id` FROM `Users` AS `User` LIMIT 1, 10000000000000;', //original 'SELECT `id` FROM `Users` AS `User` LIMIT 18446744073709551615 OFFSET 1;', + mariadb: 'SELECT `id` FROM `Users` AS `User` LIMIT 1, 10000000000000;', //original 'SELECT `id` FROM `Users` AS `User` LIMIT 18446744073709551615 OFFSET 1;', + sqlite: 'SELECT `id` FROM `Users` AS `User` LIMIT 1, 10000000000000;', //original 'SELECT `id` FROM `Users` AS `User` LIMIT -1 OFFSET 1;' + oracle: 'SELECT "id" FROM "Users" "User" ORDER BY "User"."id" OFFSET 1 ROWS;', + snowflake: 'SELECT "id" FROM "Users" AS "User" LIMIT NULL OFFSET 1;', + db2: 'SELECT "id" FROM "Users" AS "User" OFFSET 1 ROWS;', + ibmi: 'SELECT "id" FROM "Users" AS "User" OFFSET 1 ROWS', + mssql: 'SELECT [id] FROM [Users] AS [User] ORDER BY [User].[id] OFFSET 1 ROWS;' + }); + }); + + it('supports querying for bigint values', () => { + const query = sql.selectQuery(Project.tableName, { + model: Project, + attributes: ['id'], + where: { + duration: { [Op.eq]: 9007199254740993n } + } + }, Project); + + expectsql(query, { + postgres: 'SELECT "id" FROM "Projects" AS "Project" WHERE "Project"."duration" = 9007199254740993;', + mysql: 'SELECT `id` FROM `Projects` AS `Project` WHERE `Project`.`duration` = 9007199254740993;', + mariadb: 'SELECT `id` FROM `Projects` AS `Project` WHERE `Project`.`duration` = 9007199254740993;', + sqlite: 'SELECT `id` FROM `Projects` AS `Project` WHERE `Project`.`duration` = 9007199254740993;', + oracle: 'SELECT "id" FROM "Projects" "Project" WHERE "Project"."duration" = 9007199254740993;', + snowflake: 'SELECT "id" FROM "Projects" AS "Project" WHERE "Project"."duration" = 9007199254740993;', + db2: 'SELECT "id" FROM "Projects" AS "Project" WHERE "Project"."duration" = 9007199254740993;', + ibmi: 'SELECT "id" FROM "Projects" AS "Project" WHERE "Project"."duration" = \'9007199254740993\'', + mssql: 'SELECT [id] FROM [Projects] AS [Project] WHERE [Project].[duration] = 9007199254740993;' + }); + }); + + it('throws an error if encountering parentheses in an attribute', () => { + expect(() => sql.selectQuery(Project.tableName, { + model: Project, + attributes: [['count(*)', 'count']] + }, Project)).to.throw('In order to fix the vulnerability CVE-2023-22578, we had to remove support for treating attributes as raw SQL if they included parentheses.'); + }); + + it('escapes attributes with parentheses if attributeBehavior is escape', () => { + const escapeSequelize = Support.createSequelizeInstance({ + attributeBehavior: 'escape' + }); + + expectsql(escapeSequelize.queryInterface.queryGenerator.selectQuery(Project.tableName, { + model: Project, + attributes: [['count(*)', 'count']] + }, Project), { + default: 'SELECT [count(*)] AS [count] FROM [Projects] AS [Project];', + oracle: 'SELECT "count(*)" AS "count" FROM "Projects" "Project";' + }); + }); + + it('inlines attributes with parentheses if attributeBehavior is unsafe-legacy', () => { + const escapeSequelize = Support.createSequelizeInstance({ + attributeBehavior: 'unsafe-legacy' + }); + + expectsql(escapeSequelize.queryInterface.queryGenerator.selectQuery(Project.tableName, { + model: Project, + attributes: [['count(*)', 'count']] + }, Project), { + default: 'SELECT count(*) AS [count] FROM [Projects] AS [Project];', + oracle: 'SELECT count(*) AS "count" FROM "Projects" "Project";' + }); + }); + }); }); diff --git a/test/unit/sql/show-constraints.test.js b/test/unit/sql/show-constraints.test.js index aff407f49118..56ef9de590df 100644 --- a/test/unit/sql/show-constraints.test.js +++ b/test/unit/sql/show-constraints.test.js @@ -15,6 +15,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: "SELECT CONSTRAINT_CATALOG AS constraintCatalog, CONSTRAINT_NAME AS constraintName, CONSTRAINT_SCHEMA AS constraintSchema, CONSTRAINT_TYPE AS constraintType, TABLE_NAME AS tableName, TABLE_SCHEMA AS tableSchema from INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE table_name='myTable';", db2: 'SELECT CONSTNAME AS "constraintName", TRIM(TABSCHEMA) AS "schemaName", TABNAME AS "tableName" FROM SYSCAT.TABCONST WHERE TABNAME = \'myTable\' ORDER BY CONSTNAME;', snowflake: "SELECT CONSTRAINT_CATALOG AS constraintCatalog, CONSTRAINT_NAME AS constraintName, CONSTRAINT_SCHEMA AS constraintSchema, CONSTRAINT_TYPE AS constraintType, TABLE_NAME AS tableName, TABLE_SCHEMA AS tableSchema from INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE table_name='myTable';", + oracle: "SELECT CONSTRAINT_NAME constraint_name FROM user_cons_columns WHERE table_name = 'myTable'", default: "SELECT sql FROM sqlite_master WHERE tbl_name='myTable';" }); }); @@ -27,6 +28,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: "SELECT CONSTRAINT_CATALOG AS constraintCatalog, CONSTRAINT_NAME AS constraintName, CONSTRAINT_SCHEMA AS constraintSchema, CONSTRAINT_TYPE AS constraintType, TABLE_NAME AS tableName, TABLE_SCHEMA AS tableSchema from INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE table_name='myTable' AND constraint_name = 'myConstraintName';", db2: 'SELECT CONSTNAME AS "constraintName", TRIM(TABSCHEMA) AS "schemaName", TABNAME AS "tableName" FROM SYSCAT.TABCONST WHERE TABNAME = \'myTable\' AND CONSTNAME LIKE \'%myConstraintName%\' ORDER BY CONSTNAME;', snowflake: "SELECT CONSTRAINT_CATALOG AS constraintCatalog, CONSTRAINT_NAME AS constraintName, CONSTRAINT_SCHEMA AS constraintSchema, CONSTRAINT_TYPE AS constraintType, TABLE_NAME AS tableName, TABLE_SCHEMA AS tableSchema from INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE table_name='myTable' AND constraint_name = 'myConstraintName';", + oracle: "SELECT CONSTRAINT_NAME constraint_name FROM user_cons_columns WHERE table_name = 'myTable'", default: "SELECT sql FROM sqlite_master WHERE tbl_name='myTable' AND sql LIKE '%myConstraintName%';" }); }); diff --git a/test/unit/sql/update.test.js b/test/unit/sql/update.test.js index 05205ff20cd3..561206408d90 100644 --- a/test/unit/sql/update.test.js +++ b/test/unit/sql/update.test.js @@ -27,6 +27,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { { query: { db2: 'SELECT * FROM FINAL TABLE (UPDATE "users" SET "user_name"=$1 WHERE "id" = $2);', + oracle: 'UPDATE "users" SET "user_name"=:1 WHERE "id" = :2', default: 'UPDATE [users] SET [user_name]=$1 WHERE [id] = $2' }, bind: { @@ -57,6 +58,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: 'UPDATE "users" SET "user_name"=$1 WHERE "id" = $2 RETURNING "id","user_name"', db2: 'SELECT * FROM FINAL TABLE (UPDATE "users" SET "user_name"=$1 WHERE "id" = $2);', snowflake: 'UPDATE "users" SET "user_name"=$1 WHERE "id" = $2', + oracle: 'UPDATE "users" SET "user_name"=:1 WHERE "id" = :2', default: 'UPDATE `users` SET `user_name`=$1 WHERE `id` = $2' }, bind: { @@ -85,6 +87,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { sqlite: 'UPDATE `Users` SET `username`=$1 WHERE rowid IN (SELECT rowid FROM `Users` WHERE `username` = $2 LIMIT 1)', db2: 'SELECT * FROM FINAL TABLE (UPDATE (SELECT * FROM "Users" WHERE "username" = $2 FETCH NEXT 1 ROWS ONLY) SET "username"=$1);', snowflake: 'UPDATE "Users" SET "username"=$1 WHERE "username" = $2 LIMIT 1', + oracle: 'UPDATE "Users" SET "username"=:1 WHERE "username" = :2 AND rownum <= 1', default: 'UPDATE [Users] SET [username]=$1 WHERE [username] = $2' }, bind: { diff --git a/test/unit/sql/where.test.js b/test/unit/sql/where.test.js index 6ebb967d190d..02a35fb2a7b4 100644 --- a/test/unit/sql/where.test.js +++ b/test/unit/sql/where.test.js @@ -61,10 +61,20 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: 'WHERE "yolo"."User"."id" = 1', snowflake: 'WHERE "yolo"."User"."id" = 1', mariadb: 'WHERE `yolo`.`User`.`id` = 1', + oracle: 'WHERE "yolo"."User"."id" = 1', mssql: 'WHERE [yolo].[User].[id] = 1' }); }); + testsql({ + name: 'TO_DATE(\'0\',\'Y\')||\'\' OR 1=1--' + }, { + default: 'WHERE [name] = \'TO_DATE(\'\'0\'\',\'\'Y\'\')||\'\'\'\' OR 1=1--\'', + 'mariadb mysql': "WHERE `name` = 'TO_DATE(\\'0\\',\\'Y\\')||\\'\\' OR 1=1--'", + mssql: 'WHERE [name] = N\'TO_DATE(\'\'0\'\',\'\'Y\'\')||\'\'\'\' OR 1=1--\'', + oracle: new Error('Invalid SQL function call.') + }); + testsql({ name: 'a project', [Op.or]: [ @@ -96,6 +106,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { snowflake: 'WHERE "name" = \'here is a null char: \0\'', mssql: "WHERE [name] = N'here is a null char: \0'", db2: "WHERE \"name\" = 'here is a null char: \0'", + oracle: 'WHERE "name" = \'here is a null char: \0\'', sqlite: "WHERE `name` = 'here is a null char: \0'" }); }); @@ -121,6 +132,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { db2: '"deleted" IS NULL', postgres: '"deleted" IS NULL', snowflake: '"deleted" IS NULL', + oracle: '"deleted" IS NULL', mssql: '[deleted] IS NULL' }); @@ -160,6 +172,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: "`field` = X'53657175656c697a65'", db2: '"field" = BLOB(\'Sequelize\')', snowflake: '"field" = X\'53657175656c697a65\'', + oracle: '"field" = \'53657175656c697a65\'', mssql: '[field] = 0x53657175656c697a65' }); }); @@ -170,6 +183,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { }, { default: '[deleted] IS NOT true', mssql: '[deleted] IS NOT 1', + oracle: '"deleted" IS NOT 1', sqlite: '`deleted` IS NOT 1' }); @@ -505,6 +519,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mysql: "`date` BETWEEN '2013-01-01 00:00:00' AND '2013-01-11 00:00:00'", db2: "\"date\" BETWEEN '2013-01-01 00:00:00' AND '2013-01-11 00:00:00'", snowflake: '"date" BETWEEN \'2013-01-01 00:00:00\' AND \'2013-01-11 00:00:00\'', + oracle: '"date" BETWEEN TO_TIMESTAMP_TZ(\'2013-01-01 00:00:00.000 +00:00\',\'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM\') AND TO_TIMESTAMP_TZ(\'2013-01-11 00:00:00.000 +00:00\',\'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM\')', mariadb: "`date` BETWEEN '2013-01-01 00:00:00.000' AND '2013-01-11 00:00:00.000'" }); @@ -514,13 +529,22 @@ describe(Support.getTestDialectTeaser('SQL'), () => { model: { rawAttributes: { date: { - type: new DataTypes.DATE() + // We need to convert timestamp to a dialect specific date format to work as expected + // For example: Oracle database expects TO_TIMESTAMP_TZ('2013-01-01 00:00:00.000 +00:00','YYYY-MM-DD HH24:MI:SS.FFTZH:TZM') + // from a timestamp instead of '2013-01-01 00:00:00.000 +00:00' which is returned by default DATE class + + // We cannot use - type: new current.dialect.DataTypes.Date - because when dialect is set to 'mysql' + // mysql DATE class returns '2013-01-01 00:00:00' instead of '2013-01-01 00:00:00.000 +00:00'(expected) + // and that would cause this test to fail when dialect is set to 'mysql' + // So we're using - new current.dialect.DataTypes.Date - only in case when dialect is set to 'oracle' as of now + type: current.dialect.name === 'oracle' ? new current.dialect.DataTypes.DATE() : new DataTypes.DATE() } } } }, { default: "[date] BETWEEN '2013-01-01 00:00:00.000 +00:00' AND '2013-01-11 00:00:00.000 +00:00'", + oracle: '"date" BETWEEN TO_TIMESTAMP_TZ(\'2013-01-01 00:00:00.000 +00:00\',\'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM\') AND TO_TIMESTAMP_TZ(\'2013-01-11 00:00:00.000 +00:00\',\'YYYY-MM-DD HH24:MI:SS.FFTZH:TZM\')', mssql: "[date] BETWEEN N'2013-01-01 00:00:00.000 +00:00' AND N'2013-01-11 00:00:00.000 +00:00'" }); @@ -880,6 +904,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: "(\"profile\"#>>'{id}') = CAST('12346-78912' AS TEXT)", sqlite: "json_extract(`profile`,'$.id') = CAST('12346-78912' AS TEXT)", mariadb: "json_unquote(json_extract(`profile`,'$.id')) = CAST('12346-78912' AS CHAR)", + oracle: 'json_value("profile",\'$."id"\') = CAST(\'12346-78912\' AS TEXT)', mysql: "json_unquote(json_extract(`profile`,'$.\\\"id\\\"')) = CAST('12346-78912' AS CHAR)" }); }); @@ -889,6 +914,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { postgres: "(\"profile\"#>>'{id}') = '12346-78912' AND (\"profile\"#>>'{name}') = 'test'", sqlite: "json_extract(`profile`,'$.id') = '12346-78912' AND json_extract(`profile`,'$.name') = 'test'", mariadb: "json_unquote(json_extract(`profile`,'$.id')) = '12346-78912' AND json_unquote(json_extract(`profile`,'$.name')) = 'test'", + oracle: 'json_value("profile",\'$."id"\') = \'12346-78912\' AND json_value("profile",\'$."name"\') = \'test\'', mysql: "json_unquote(json_extract(`profile`,'$.\\\"id\\\"')) = '12346-78912' AND json_unquote(json_extract(`profile`,'$.\\\"name\\\"')) = 'test'" }); }); @@ -906,6 +932,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "json_unquote(json_extract(`User`.`data`,'$.nested.attribute')) = 'value'", mysql: "json_unquote(json_extract(`User`.`data`,'$.\\\"nested\\\".\\\"attribute\\\"')) = 'value'", postgres: "(\"User\".\"data\"#>>'{nested,attribute}') = 'value'", + oracle: 'json_value("User"."data",\'$."nested"."attribute"\') = \'value\'', sqlite: "json_extract(`User`.`data`,'$.nested.attribute') = 'value'" }); @@ -921,6 +948,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested')) AS DECIMAL) IN (1, 2)", mysql: "CAST(json_unquote(json_extract(`data`,'$.\\\"nested\\\"')) AS DECIMAL) IN (1, 2)", postgres: "CAST((\"data\"#>>'{nested}') AS DOUBLE PRECISION) IN (1, 2)", + oracle: 'CAST(json_value("data",\'$."nested"\') AS DOUBLE PRECISION) IN (1, 2)', sqlite: "CAST(json_extract(`data`,'$.nested') AS DOUBLE PRECISION) IN (1, 2)" }); @@ -936,6 +964,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested')) AS DECIMAL) BETWEEN 1 AND 2", mysql: "CAST(json_unquote(json_extract(`data`,'$.\\\"nested\\\"')) AS DECIMAL) BETWEEN 1 AND 2", postgres: "CAST((\"data\"#>>'{nested}') AS DOUBLE PRECISION) BETWEEN 1 AND 2", + oracle: 'CAST(json_value("data",\'$."nested"\') AS DOUBLE PRECISION) BETWEEN 1 AND 2', sqlite: "CAST(json_extract(`data`,'$.nested') AS DOUBLE PRECISION) BETWEEN 1 AND 2" }); @@ -955,6 +984,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "(json_unquote(json_extract(`User`.`data`,'$.nested.attribute')) = 'value' AND json_unquote(json_extract(`User`.`data`,'$.nested.prop')) != 'None')", mysql: "(json_unquote(json_extract(`User`.`data`,'$.\\\"nested\\\".\\\"attribute\\\"')) = 'value' AND json_unquote(json_extract(`User`.`data`,'$.\\\"nested\\\".\\\"prop\\\"')) != 'None')", postgres: "((\"User\".\"data\"#>>'{nested,attribute}') = 'value' AND (\"User\".\"data\"#>>'{nested,prop}') != 'None')", + oracle: '(json_value("User"."data",\'$."nested"."attribute"\') = \'value\' AND json_value("User"."data",\'$."nested"."prop"\') != \'None\')', sqlite: "(json_extract(`User`.`data`,'$.nested.attribute') = 'value' AND json_extract(`User`.`data`,'$.nested.prop') != 'None')" }); @@ -974,6 +1004,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "(json_unquote(json_extract(`User`.`data`,'$.name.last')) = 'Simpson' AND json_unquote(json_extract(`User`.`data`,'$.employment')) != 'None')", mysql: "(json_unquote(json_extract(`User`.`data`,'$.\\\"name\\\".\\\"last\\\"')) = 'Simpson' AND json_unquote(json_extract(`User`.`data`,'$.\\\"employment\\\"')) != 'None')", postgres: "((\"User\".\"data\"#>>'{name,last}') = 'Simpson' AND (\"User\".\"data\"#>>'{employment}') != 'None')", + oracle: '(json_value("User"."data",\'$."name"."last"\') = \'Simpson\' AND json_value("User"."data",\'$."employment"\') != \'None\')', sqlite: "(json_extract(`User`.`data`,'$.name.last') = 'Simpson' AND json_extract(`User`.`data`,'$.employment') != 'None')" }); @@ -988,6 +1019,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "(CAST(json_unquote(json_extract(`data`,'$.price')) AS DECIMAL) = 5 AND json_unquote(json_extract(`data`,'$.name')) = 'Product')", mysql: "(CAST(json_unquote(json_extract(`data`,'$.\\\"price\\\"')) AS DECIMAL) = 5 AND json_unquote(json_extract(`data`,'$.\\\"name\\\"')) = 'Product')", postgres: "(CAST((\"data\"#>>'{price}') AS DOUBLE PRECISION) = 5 AND (\"data\"#>>'{name}') = 'Product')", + oracle: '(CAST(json_value("data",\'$."price"\') AS DOUBLE PRECISION) = 5 AND json_value("data",\'$."name"\') = \'Product\')', sqlite: "(CAST(json_extract(`data`,'$.price') AS DOUBLE PRECISION) = 5 AND json_extract(`data`,'$.name') = 'Product')" }); @@ -1003,6 +1035,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "json_unquote(json_extract(`data`,'$.nested.attribute')) = 'value'", mysql: "json_unquote(json_extract(`data`,'$.\\\"nested\\\".\\\"attribute\\\"')) = 'value'", postgres: "(\"data\"#>>'{nested,attribute}') = 'value'", + oracle: 'json_value("data",\'$."nested"."attribute"\') = \'value\'', sqlite: "json_extract(`data`,'$.nested.attribute') = 'value'" }); @@ -1018,6 +1051,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) = 4", mysql: "CAST(json_unquote(json_extract(`data`,'$.\\\"nested\\\".\\\"attribute\\\"')) AS DECIMAL) = 4", postgres: "CAST((\"data\"#>>'{nested,attribute}') AS DOUBLE PRECISION) = 4", + oracle: 'CAST(json_value("data",\'$."nested"."attribute"\') AS DOUBLE PRECISION) = 4', sqlite: "CAST(json_extract(`data`,'$.nested.attribute') AS DOUBLE PRECISION) = 4" }); @@ -1035,6 +1069,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) IN (3, 7)", mysql: "CAST(json_unquote(json_extract(`data`,'$.\\\"nested\\\".\\\"attribute\\\"')) AS DECIMAL) IN (3, 7)", postgres: "CAST((\"data\"#>>'{nested,attribute}') AS DOUBLE PRECISION) IN (3, 7)", + oracle: 'CAST(json_value("data",\'$."nested"."attribute"\') AS DOUBLE PRECISION) IN (3, 7)', sqlite: "CAST(json_extract(`data`,'$.nested.attribute') AS DOUBLE PRECISION) IN (3, 7)" }); @@ -1052,6 +1087,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) > 2", mysql: "CAST(json_unquote(json_extract(`data`,'$.\\\"nested\\\".\\\"attribute\\\"')) AS DECIMAL) > 2", postgres: "CAST((\"data\"#>>'{nested,attribute}') AS DOUBLE PRECISION) > 2", + oracle: 'CAST(json_value("data",\'$."nested"."attribute"\') AS DOUBLE PRECISION) > 2', sqlite: "CAST(json_extract(`data`,'$.nested.attribute') AS DOUBLE PRECISION) > 2" }); @@ -1069,6 +1105,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "CAST(json_unquote(json_extract(`data`,'$.nested.attribute')) AS DECIMAL) > 2", mysql: "CAST(json_unquote(json_extract(`data`,'$.\\\"nested\\\".\\\"attribute\\\"')) AS DECIMAL) > 2", postgres: "CAST((\"data\"#>>'{nested,attribute}') AS INTEGER) > 2", + oracle: 'CAST(json_value("data",\'$."nested"."attribute"\') AS INTEGER) > 2', sqlite: "CAST(json_extract(`data`,'$.nested.attribute') AS INTEGER) > 2" }); @@ -1087,6 +1124,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: `CAST(json_unquote(json_extract(\`data\`,'$.nested.attribute')) AS DATETIME) > ${sql.escape(dt)}`, mysql: `CAST(json_unquote(json_extract(\`data\`,'$.\\"nested\\".\\"attribute\\"')) AS DATETIME) > ${sql.escape(dt)}`, postgres: `CAST(("data"#>>'{nested,attribute}') AS TIMESTAMPTZ) > ${sql.escape(dt)}`, + oracle: `json_value("data",'$."nested"."attribute"' RETURNING TIMESTAMP WITH TIME ZONE) > ${sql.escape(dt)}`, sqlite: `json_extract(\`data\`,'$.nested.attribute') > ${sql.escape(dt.toISOString())}` }); @@ -1102,6 +1140,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "json_unquote(json_extract(`data`,'$.nested.attribute')) = 'true'", mysql: "json_unquote(json_extract(`data`,'$.\\\"nested\\\".\\\"attribute\\\"')) = 'true'", postgres: "CAST((\"data\"#>>'{nested,attribute}') AS BOOLEAN) = true", + oracle: 'CAST((CASE WHEN json_value("data",\'$."nested"."attribute"\')=\'true\' THEN 1 ELSE 0 END) AS NUMBER) = 1', sqlite: "CAST(json_extract(`data`,'$.nested.attribute') AS BOOLEAN) = 1" }); @@ -1119,6 +1158,7 @@ describe(Support.getTestDialectTeaser('SQL'), () => { mariadb: "json_unquote(json_extract(`meta_data`,'$.nested.attribute')) = 'value'", mysql: "json_unquote(json_extract(`meta_data`,'$.\\\"nested\\\".\\\"attribute\\\"')) = 'value'", postgres: "(\"meta_data\"#>>'{nested,attribute}') = 'value'", + oracle: 'json_value("meta_data",\'$."nested"."attribute"\') = \'value\'', sqlite: "json_extract(`meta_data`,'$.nested.attribute') = 'value'" }); }); diff --git a/test/unit/transaction.test.js b/test/unit/transaction.test.js index 6fea3c631274..639b9ea9519c 100644 --- a/test/unit/transaction.test.js +++ b/test/unit/transaction.test.js @@ -46,6 +46,9 @@ describe('Transaction', () => { ], mssql: [ 'BEGIN TRANSACTION;' + ], + oracle: [ + 'BEGIN TRANSACTION' ] }; @@ -73,6 +76,10 @@ describe('Transaction', () => { ], mssql: [ 'BEGIN TRANSACTION;' + ], + oracle: [ + 'BEGIN TRANSACTION', + 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED;' ] }; diff --git a/test/unit/utils.test.js b/test/unit/utils.test.js index 5f921deab56b..302978699049 100644 --- a/test/unit/utils.test.js +++ b/test/unit/utils.test.js @@ -71,14 +71,14 @@ describe(Support.getTestDialectTeaser('Utils'), () => { it('defaults symbol keys', () => { expect(Utils.defaults( - { a: 1, [Symbol.for('c')]: 3 }, + { a: 1, [Symbol.for('eq')]: 3 }, { b: 2 }, - { [Symbol.for('c')]: 4, [Symbol.for('d')]: 4 } + { [Symbol.for('eq')]: 4, [Symbol.for('ne')]: 4 } )).to.eql({ a: 1, b: 2, - [Symbol.for('c')]: 3, - [Symbol.for('d')]: 4 + [Symbol.for('eq')]: 3, + [Symbol.for('ne')]: 4 }); }); }); diff --git a/test/unit/utils/sql.test.js b/test/unit/utils/sql.test.js index eea503679cd6..f529b35d3dd4 100644 --- a/test/unit/utils/sql.test.js +++ b/test/unit/utils/sql.test.js @@ -1,6 +1,12 @@ const { injectReplacements } = require('sequelize/lib/utils/sql'); const { expect } = require('chai'); -const { expectsql, sequelize } = require('../../support'); +const { + expectsql, + sequelize, + createSequelizeInstance, + expectPerDialect, + toMatchSql +} = require('../../support'); const dialect = sequelize.dialect; @@ -21,7 +27,6 @@ describe('injectReplacements (named replacements)', () => { id: 1 }); }).to.throw('Named replacement ":toString" has no entry in the replacement map.'); - }); it('parses named replacements followed by cast syntax', () => { @@ -34,6 +39,56 @@ describe('injectReplacements (named replacements)', () => { }); }); + it('parses named replacements following JSONB indexing', () => { + const sql = injectReplacements( + 'SELECT * FROM users WHERE json_col->>:key', + dialect, + { key: 'name' } + ); + + expectsql(sql, { + default: "SELECT * FROM users WHERE json_col->>'name'", + mssql: "SELECT * FROM users WHERE json_col->>N'name'" + }); + }); + + it('parses named replacements followed by a semicolon', () => { + const sql = injectReplacements('SELECT * FROM users WHERE id = :id;', dialect, { + id: 1 + }); + + expectsql(sql, { + default: 'SELECT * FROM users WHERE id = 1;' + }); + }); + + it('parses bind parameters following JSONB indexing', () => { + const sql = injectReplacements( + 'SELECT * FROM users WHERE json_col->>$key', + dialect, + { id: 1 } + ); + + expectsql(sql, { + default: 'SELECT * FROM users WHERE json_col->>$key' + }); + }); + + // this is a workaround. + // The right way to support ARRAY in replacement is https://github.com/sequelize/sequelize/issues/14410 + if (sequelize.dialect.supports.ARRAY) { + it('parses named replacements inside ARRAY[]', () => { + const sql = injectReplacements('SELECT * FROM users WHERE id = ARRAY[:id1]::int[] OR id = ARRAY[:id1,:id2]::int[] OR id = ARRAY[:id1, :id2]::int[];', dialect, { + id1: 1, + id2: 4 + }); + + expectsql(sql, { + default: 'SELECT * FROM users WHERE id = ARRAY[1]::int[] OR id = ARRAY[1,4]::int[] OR id = ARRAY[1, 4]::int[];' + }); + }); + } + it('parses single letter named replacements', () => { const sql = injectReplacements('SELECT * FROM users WHERE id = :a', dialect, { a: 1 @@ -84,16 +139,94 @@ describe('injectReplacements (named replacements)', () => { }); }); - it('does not consider the token to be a replacement if it is part of a string with a backslash escaped quote', () => { - const sql = injectReplacements('SELECT * FROM users WHERE id = \'\\\':id\' OR id = :id', dialect, { + it('does consider the token to be a bind parameter if it is located after a $ quoted string', () => { + const sql = injectReplacements('SELECT $$ abc $$ AS string FROM users WHERE id = :id', dialect, { id: 1 }); expectsql(sql, { - default: 'SELECT * FROM users WHERE id = \'\\\':id\' OR id = 1' + default: 'SELECT $$ abc $$ AS string FROM users WHERE id = 1' }); }); + it('does not consider the token to be a bind parameter if it is part of a string with a backslash escaped quote, in dialects that support backslash escape', () => { + expectPerDialect( + () => + injectReplacements( + "SELECT * FROM users WHERE id = '\\' $id' OR id = $id", + dialect, + { id: 1 } + ), + { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = '\\' $id' OR id = $id`), + 'mysql mariadb': toMatchSql( + "SELECT * FROM users WHERE id = '\\' $id' OR id = $id" + ) + } + ); + }); + + it('does not consider the token to be a bind parameter if it is part of a string with a backslash escaped quote, in dialects that support standardConformingStrings = false', () => { + expectPerDialect( + () => + injectReplacements( + "SELECT * FROM users WHERE id = '\\' $id' OR id = $id", + getNonStandardConfirmingStringDialect(), + { id: 1 } + ), + { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = '\\' $id' OR id = $id`), + + 'mysql mariadb postgres': toMatchSql( + "SELECT * FROM users WHERE id = '\\' $id' OR id = $id" + ) + } + ); + }); + + it('does not consider the token to be a bind parameter if it is part of an E-prefixed string with a backslash escaped quote, in dialects that support E-prefixed strings', () => { + expectPerDialect( + () => + injectReplacements( + "SELECT * FROM users WHERE id = E'\\' $id' OR id = $id", + dialect, + { id: 1 } + ), + { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = E'\\' $id' OR id = $id`), + 'mysql mariadb postgres': toMatchSql( + "SELECT * FROM users WHERE id = E'\\' $id' OR id = $id" + ) + } + ); + }); + + it('treats strings prefixed with a lowercase e as E-prefixed strings too', () => { + expectPerDialect( + () => + injectReplacements( + "SELECT * FROM users WHERE id = e'\\' $id' OR id = $id", + dialect, + { id: 1 } + ), + { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = e'\\' $id' OR id = $id`), + + 'mysql mariadb postgres': toMatchSql( + "SELECT * FROM users WHERE id = e'\\' $id' OR id = $id" + ) + } + ); + }); + it('considers the token to be a replacement if it is outside a string ending with an escaped backslash', () => { const sql = injectReplacements('SELECT * FROM users WHERE id = \'\\\\\' OR id = :id', dialect, { id: 1 @@ -105,12 +238,19 @@ describe('injectReplacements (named replacements)', () => { }); it('does not consider the token to be a replacement if it is part of a string with an escaped backslash followed by a backslash escaped quote', () => { - const sql = injectReplacements('SELECT * FROM users WHERE id = \'\\\\\\\':id\' OR id = :id', dialect, { - id: 1 - }); + const test = () => + injectReplacements( + "SELECT * FROM users WHERE id = '\\\\\\' :id' OR id = :id", + dialect, + { id: 1 } + ); - expectsql(sql, { - default: 'SELECT * FROM users WHERE id = \'\\\\\\\':id\' OR id = 1' + expectPerDialect(test, { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = '\\\\\\' :id' OR id = :id`), + + 'mysql mariadb': "SELECT * FROM users WHERE id = '\\\\\\' :id' OR id = 1" }); }); @@ -182,6 +322,39 @@ describe('injectReplacements (positional replacements)', () => { }); }); + it('parses named replacements following JSONB indexing', () => { + const sql = injectReplacements( + 'SELECT * FROM users WHERE json_col->>?', + dialect, + ['name'] + ); + + expectsql(sql, { + default: "SELECT * FROM users WHERE json_col->>'name'", + mssql: "SELECT * FROM users WHERE json_col->>N'name'" + }); + }); + + it('parses positional replacements followed by a semicolon', () => { + const sql = injectReplacements('SELECT * FROM users WHERE id = ?;', dialect, [1]); + + expectsql(sql, { + default: 'SELECT * FROM users WHERE id = 1;' + }); + }); + + // this is a workaround. + // The right way to support ARRAY in replacement is https://github.com/sequelize/sequelize/issues/14410 + if (sequelize.dialect.supports.ARRAY) { + it('parses positional replacements inside ARRAY[]', () => { + const sql = injectReplacements('SELECT * FROM users WHERE id = ARRAY[?]::int[] OR ARRAY[?,?]::int[] OR ARRAY[?, ?]::int[];', dialect, [1, 1, 4, 1, 4]); + + expectsql(sql, { + default: 'SELECT * FROM users WHERE id = ARRAY[1]::int[] OR ARRAY[1,4]::int[] OR ARRAY[1, 4]::int[];' + }); + }); + } + it('does not consider the token to be a replacement if it does not follow \'(\', \',\', \'=\' or whitespace', () => { const sql = injectReplacements('SELECT * FROM users WHERE id = fn(?) OR id = fn(\'a\',?) OR id=? OR id = ?', dialect, [2, 1, 3, 4]); @@ -214,14 +387,80 @@ describe('injectReplacements (positional replacements)', () => { }); }); - it('does not consider the token to be a replacement if it is part of a string with a backslash escaped quote', () => { - const sql = injectReplacements('SELECT * FROM users WHERE id = \'\\\'?\' OR id = ?', dialect, [1]); + it('does not consider the token to be a replacement if it is in an unnamed $ quoted string', () => { + const sql = injectReplacements('SELECT $$ ? $$', dialect, [1]); + + expectsql(sql, { + default: 'SELECT $$ ? $$' + }); + }); + + it('does consider the token to be a replacement if it is located after a $ quoted string', () => { + const sql = injectReplacements('SELECT $$ abc $$ AS string FROM users WHERE id = ?', dialect, [1]); expectsql(sql, { - default: 'SELECT * FROM users WHERE id = \'\\\'?\' OR id = 1' + default: 'SELECT $$ abc $$ AS string FROM users WHERE id = 1' + }); + }); + + it('does not consider the token to be a replacement if it is part of a string with a backslash escaped quote', () => { + const test = () => + injectReplacements( + "SELECT * FROM users WHERE id = '\\' :id' OR id = :id", + dialect, + { id: 1 } + ); + + expectPerDialect(test, { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = '\\' :id' OR id = :id`), + + 'mysql mariadb': toMatchSql( + "SELECT * FROM users WHERE id = '\\' :id' OR id = 1" + ) }); }); + it('does not consider the token to be a replacement if it is part of a string with a backslash escaped quote, in dialects that support standardConformingStrings = false', () => { + const test = () => + injectReplacements( + "SELECT * FROM users WHERE id = '\\' :id' OR id = :id", + getNonStandardConfirmingStringDialect(), + { id: 1 } + ); + + expectPerDialect(test, { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = '\\' :id' OR id = :id`), + + 'mysql mariadb postgres': toMatchSql( + "SELECT * FROM users WHERE id = '\\' :id' OR id = 1" + ) + }); + }); + + it('does not consider the token to be a replacement if it is part of an E-prefixed string with a backslash escaped quote, in dialects that support E-prefixed strings', () => { + expectPerDialect( + () => + injectReplacements( + "SELECT * FROM users WHERE id = E'\\' :id' OR id = :id", + dialect, + { id: 1 } + ), + { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = E'\\' :id' OR id = :id`), + + 'mysql mariadb postgres': toMatchSql( + "SELECT * FROM users WHERE id = E'\\' :id' OR id = 1" + ) + } + ); + }); + it('considers the token to be a replacement if it is outside a string ending with an escaped backslash', () => { const sql = injectReplacements('SELECT * FROM users WHERE id = \'\\\\\' OR id = ?', dialect, [1]); @@ -231,10 +470,19 @@ describe('injectReplacements (positional replacements)', () => { }); it('does not consider the token to be a replacement if it is part of a string with an escaped backslash followed by a backslash escaped quote', () => { - const sql = injectReplacements('SELECT * FROM users WHERE id = \'\\\\\\\'?\' OR id = ?', dialect, [1]); + const test = () => + injectReplacements( + "SELECT * FROM users WHERE id = '\\\\\\' :id' OR id = :id", + dialect, + { id: 1 } + ); - expectsql(sql, { - default: 'SELECT * FROM users WHERE id = \'\\\\\\\'?\' OR id = 1' + expectPerDialect(test, { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = '\\\\\\' :id' OR id = :id`), + + 'mysql mariadb': "SELECT * FROM users WHERE id = '\\\\\\' :id' OR id = 1" }); }); @@ -324,4 +572,84 @@ describe('injectReplacements (positional replacements)', () => { (N'michael', N'michael@gmail.com', N'2012-01-01 10:10:10', N'2012-01-01 10:10:10');` }); }); + + it('does not consider the token to be a replacement if it is part of a string with a backslash escaped quote', () => { + const test = () => + injectReplacements( + "SELECT * FROM users WHERE id = '\\' ?' OR id = ?", + dialect, + [1] + ); + expectPerDialect(test, { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = '\\' ?' OR id = ?`), + + 'mysql mariadb': toMatchSql( + "SELECT * FROM users WHERE id = '\\' ?' OR id = 1" + ) + }); + }); + + it('does not consider the token to be a replacement if it is part of a string with a backslash escaped quote, in dialects that support standardConformingStrings = false', () => { + const test = () => + injectReplacements( + "SELECT * FROM users WHERE id = '\\' ?' OR id = ?", + getNonStandardConfirmingStringDialect(), + [1] + ); + + expectPerDialect(test, { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = '\\' ?' OR id = ?`), + + 'mysql mariadb postgres': toMatchSql( + "SELECT * FROM users WHERE id = '\\' ?' OR id = 1" + ) + }); + }); + + it('does not consider the token to be a replacement if it is part of an E-prefixed string with a backslash escaped quote, in dialects that support E-prefixed strings', () => { + expectPerDialect( + () => + injectReplacements( + "SELECT * FROM users WHERE id = E'\\' ?' OR id = ?", + dialect, + [1] + ), + { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = E'\\' ?' OR id = ?`), + + 'mysql mariadb postgres': toMatchSql( + "SELECT * FROM users WHERE id = E'\\' ?' OR id = 1" + ) + } + ); + }); + + it('does not consider the token to be a replacement if it is part of a string with an escaped backslash followed by a backslash escaped quote', () => { + const test = () => + injectReplacements( + "SELECT * FROM users WHERE id = '\\\\\\' ?' OR id = ?", + dialect, + [1] + ); + + expectPerDialect(test, { + default: + new Error(`The following SQL query includes an unterminated string literal: +SELECT * FROM users WHERE id = '\\\\\\' ?' OR id = ?`), + + 'mysql mariadb': "SELECT * FROM users WHERE id = '\\\\\\' ?' OR id = 1" + }); + }); }); + +function getNonStandardConfirmingStringDialect() { + return createSequelizeInstance({ + standardConformingStrings: false + }).dialect; +} diff --git a/yarn.lock b/yarn.lock index 514efe1607bd..df0630d12ab0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,70 +2,64 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" - integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== dependencies: - "@jridgewell/trace-mapping" "^0.3.0" + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" "@azure/abort-controller@^1.0.0": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.0.4.tgz#fd3c4d46c8ed67aace42498c8e2270960250eafd" - integrity sha512-lNUmDRVGpanCsiUN3NWxFTdwmdFI53xwhkTFfHDGTYk46ca7Ind3nanJc+U6Zj9Tv+9nTCWRBscWEW1DyKOpTw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" + integrity sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw== dependencies: - tslib "^2.0.0" - -"@azure/core-asynciterator-polyfill@^1.0.0": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz#0dd3849fb8d97f062a39db0e5cadc9ffaf861fec" - integrity sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw== + tslib "^2.2.0" "@azure/core-auth@^1.1.4", "@azure/core-auth@^1.3.0": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.3.2.tgz#6a2c248576c26df365f6c7881ca04b7f6d08e3d0" - integrity sha512-7CU6DmCHIZp5ZPiZ9r3J17lTKMmYsm/zGvNkjArQwPkrLlZ1TZ+EUYfGgh2X31OLMVAQCTJZW4cXHJi02EbJnA== + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.4.0.tgz#6fa9661c1705857820dbc216df5ba5665ac36a9e" + integrity sha512-HFrcTgmuSuukRf/EdPmqBrc5l6Q5Uu+2TbuhaKbgaCpP2TfAeiNaQPAadxO+CYBRHGUzIDteMAjFspFLDLnKVQ== dependencies: "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-http@^2.0.0": - version "2.2.4" - resolved "https://registry.yarnpkg.com/@azure/core-http/-/core-http-2.2.4.tgz#df5a5b4138dbbc4299879f2fc6f257d0a5f0401e" - integrity sha512-QmmJmexXKtPyc3/rsZR/YTLDvMatzbzAypJmLzvlfxgz/SkgnqV/D4f6F2LsK6tBj1qhyp8BoXiOebiej0zz3A== +"@azure/core-http@^3.0.0": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@azure/core-http/-/core-http-3.0.2.tgz#970c5a0ee27884d60a406eeec17a271413e45ff4" + integrity sha512-o1wR9JrmoM0xEAa0Ue7Sp8j+uJvmqYaGoHOCT5qaVYmvgmnZDC0OvQimPA/JR3u77Sz6D1y3Xmk1y69cDU9q9A== dependencies: "@azure/abort-controller" "^1.0.0" - "@azure/core-asynciterator-polyfill" "^1.0.0" "@azure/core-auth" "^1.3.0" "@azure/core-tracing" "1.0.0-preview.13" + "@azure/core-util" "^1.1.1" "@azure/logger" "^1.0.0" "@types/node-fetch" "^2.5.0" "@types/tunnel" "^0.0.3" form-data "^4.0.0" node-fetch "^2.6.7" process "^0.11.10" - tough-cookie "^4.0.0" tslib "^2.2.0" tunnel "^0.0.6" uuid "^8.3.0" - xml2js "^0.4.19" + xml2js "^0.5.0" "@azure/core-lro@^2.2.0": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.2.2.tgz#1f81a712d6bea6912918c5157553e6c7883e08d9" - integrity sha512-pn30b+HyJHg0+G4ZRgpL3BJa6LQnKdKl1X4JDMpuVsX+kPxs2FNoweNqD3Li199ROroIvFbi6pE29y0J2vvyIg== + version "2.5.3" + resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.5.3.tgz#6bb74e76dd84071d319abf7025e8abffef091f91" + integrity sha512-ubkOf2YCnVtq7KqEJQqAI8dDD5rH1M6OP5kW0KO/JQyTaxLA0N0pjFWvvaysCj9eHMNBcuuoZXhhl0ypjod2DA== dependencies: "@azure/abort-controller" "^1.0.0" - "@azure/core-tracing" "1.0.0-preview.13" + "@azure/core-util" "^1.2.0" "@azure/logger" "^1.0.0" tslib "^2.2.0" "@azure/core-paging@^1.1.1": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@azure/core-paging/-/core-paging-1.2.0.tgz#3754da429e8687bdc3613c750e79a564582e802b" - integrity sha512-ZX1bCjm/MjKPCN6kQD/9GJErYSoKA8YWp6YWoo5EIzcTWlSBLXu3gNaBTUl8usGl+UShiKo7b4Gdy1NSTIlpZg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-paging/-/core-paging-1.5.0.tgz#5a5b09353e636072e6a7fc38f7879e11d0afb15f" + integrity sha512-zqWdVIt+2Z+3wqxEOGzR5hXFZ8MGKK52x4vFLw8n58pR6ZfKRx3EXYTxTaYxYHc/PexPUTyimcTWFJbji9Z6Iw== dependencies: - "@azure/core-asynciterator-polyfill" "^1.0.0" tslib "^2.2.0" "@azure/core-tracing@1.0.0-preview.13": @@ -76,10 +70,18 @@ "@opentelemetry/api" "^1.0.1" tslib "^2.2.0" +"@azure/core-util@^1.1.1", "@azure/core-util@^1.2.0": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.3.2.tgz#3f8cfda1e87fac0ce84f8c1a42fcd6d2a986632d" + integrity sha512-2bECOUh88RvL1pMZTcc6OzfobBeWDBf5oBbhjIhT1MV9otMVWCzpOJkkiKtrnO88y5GGBelgY8At73KGAdbkeQ== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + "@azure/logger@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" - integrity sha512-aK4s3Xxjrx3daZr3VylxejK3vG5ExXck5WOHDJ8in/k9AqlfIyFMMT1uG7u8mNjX+QRILTIn0/Xgschfh/dQ9g== + version "1.0.4" + resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.4.tgz#28bc6d0e5b3c38ef29296b32d35da4e483593fa1" + integrity sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg== dependencies: tslib "^2.2.0" @@ -111,13 +113,13 @@ "@azure/ms-rest-js" "^1.8.7" adal-node "^0.1.28" -"@azure/storage-blob@^12.5.0": - version "12.8.0" - resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.8.0.tgz#97b7ecc6c7b17bcbaf0281c79c16af6f512d6130" - integrity sha512-c8+Wz19xauW0bGkTCoqZH4dYfbtBniPiGiRQOn1ca6G5jsjr4azwaTk9gwjVY8r3vY2Taf95eivLzipfIfiS4A== +"@azure/storage-blob@^12.11.0": + version "12.14.0" + resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.14.0.tgz#32d3e5fa3bb2a12d5d44b186aed11c8e78f00178" + integrity sha512-g8GNUDpMisGXzBeD+sKphhH5yLwesB4JkHr1U6be/X3F+cAMcyGLPD1P89g2M7wbEtUJWoikry1rlr83nNRBzg== dependencies: "@azure/abort-controller" "^1.0.0" - "@azure/core-http" "^2.0.0" + "@azure/core-http" "^3.0.0" "@azure/core-lro" "^2.2.0" "@azure/core-paging" "^1.1.1" "@azure/core-tracing" "1.0.0-preview.13" @@ -125,187 +127,185 @@ events "^3.0.0" tslib "^2.2.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" + integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== dependencies: - "@babel/highlight" "^7.16.7" + "@babel/highlight" "^7.22.5" -"@babel/compat-data@^7.16.4": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34" - integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== +"@babel/compat-data@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.5.tgz#b1f6c86a02d85d2dd3368a2b67c09add8cd0c255" + integrity sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA== "@babel/core@^7.7.5": - version "7.17.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225" - integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helpers" "^7.17.2" - "@babel/parser" "^7.17.3" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.5.tgz#d67d9747ecf26ee7ecd3ebae1ee22225fe902a89" + integrity sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.5" + "@babel/generator" "^7.22.5" + "@babel/helper-compilation-targets" "^7.22.5" + "@babel/helper-module-transforms" "^7.22.5" + "@babel/helpers" "^7.22.5" + "@babel/parser" "^7.22.5" + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.5" + "@babel/types" "^7.22.5" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.1.2" + json5 "^2.2.2" semver "^6.3.0" -"@babel/generator@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200" - integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== +"@babel/generator@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.5.tgz#1e7bf768688acfb05cf30b2369ef855e82d984f7" + integrity sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA== dependencies: - "@babel/types" "^7.17.0" + "@babel/types" "^7.22.5" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" - source-map "^0.5.0" -"@babel/helper-compilation-targets@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" - integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== +"@babel/helper-compilation-targets@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz#fc7319fc54c5e2fa14b2909cf3c5fd3046813e02" + integrity sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw== dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.17.5" + "@babel/compat-data" "^7.22.5" + "@babel/helper-validator-option" "^7.22.5" + browserslist "^4.21.3" + lru-cache "^5.1.1" semver "^6.3.0" -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== - dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-get-function-arity@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" - integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-transforms@^7.16.7": - version "7.17.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz#3c3b03cc6617e33d68ef5a27a67419ac5199ccd0" - integrity sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - -"@babel/helper-simple-access@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" - integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - -"@babel/helpers@^7.17.2": - version "7.17.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" - integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== - dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" - "@babel/types" "^7.17.0" - -"@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" +"@babel/helper-environment-visitor@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" + integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== + +"@babel/helper-function-name@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" + integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== + dependencies: + "@babel/template" "^7.22.5" + "@babel/types" "^7.22.5" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-module-imports@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" + integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-module-transforms@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz#0f65daa0716961b6e96b164034e737f60a80d2ef" + integrity sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.5" + "@babel/types" "^7.22.5" + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz#88cf11050edb95ed08d596f7a044462189127a08" + integrity sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + +"@babel/helper-validator-identifier@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" + integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== + +"@babel/helper-validator-option@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" + integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== + +"@babel/helpers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.5.tgz#74bb4373eb390d1ceed74a15ef97767e63120820" + integrity sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q== + dependencies: + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.5" + "@babel/types" "^7.22.5" + +"@babel/highlight@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" + integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw== + dependencies: + "@babel/helper-validator-identifier" "^7.22.5" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.16.7", "@babel/parser@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" - integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== - -"@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" - integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.3" - "@babel/types" "^7.17.0" +"@babel/parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea" + integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q== + +"@babel/template@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" + integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== + dependencies: + "@babel/code-frame" "^7.22.5" + "@babel/parser" "^7.22.5" + "@babel/types" "^7.22.5" + +"@babel/traverse@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.5.tgz#44bd276690db6f4940fdb84e1cb4abd2f729ccd1" + integrity sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ== + dependencies: + "@babel/code-frame" "^7.22.5" + "@babel/generator" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.5" + "@babel/parser" "^7.22.5" + "@babel/types" "^7.22.5" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.16.7", "@babel/types@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== +"@babel/types@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" + integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== dependencies: - "@babel/helper-validator-identifier" "^7.16.7" + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" "@colors/colors@1.5.0": @@ -477,43 +477,106 @@ ts-node "^9" tslib "^2" -"@es-joy/jsdoccomment@0.13.0": - version "0.13.0" - resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.13.0.tgz#90ffe2006981ff66d3f4fd2f05949487f0fca089" - integrity sha512-APVqbVPGOprb4BmjEnwbSzV+V2e/6DVIUnZG3zdW5uWXWkN0DKMCpiIy2TdBauoANKYO7RQpO8cTjIYNVSKwUA== +"@es-joy/jsdoccomment@~0.20.1": + version "0.20.1" + resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.20.1.tgz#fe89f435f045ae5aaf89c7a4df3616c03e9d106e" + integrity sha512-oeJK41dcdqkvdZy/HctKklJNkt/jh+av3PZARrZEl+fs/8HaHeeYoAvEwOV0u5I6bArTF17JEsTZMY359e/nfQ== dependencies: comment-parser "1.3.0" esquery "^1.4.0" - jsdoc-type-pratt-parser "2.0.0" + jsdoc-type-pratt-parser "~2.2.3" -"@eslint/eslintrc@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" - integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ== +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" + integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== + +"@eslint/eslintrc@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331" + integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.2.0" - globals "^13.9.0" - ignore "^4.0.6" + espree "^9.5.2" + globals "^13.19.0" + ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" - minimatch "^3.0.4" + minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@eslint/js@8.42.0": + version "8.42.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.42.0.tgz#484a1d638de2911e6f5a30c12f49c7e4a3270fb6" + integrity sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw== + "@gar/promisify@^1.0.1": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== -"@humanwhocodes/config-array@^0.9.2": - version "0.9.5" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" - integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== +"@google-cloud/paginator@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.7.tgz#fb6f8e24ec841f99defaebf62c75c2e744dd419b" + integrity sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ== + dependencies: + arrify "^2.0.0" + extend "^3.0.2" + +"@google-cloud/projectify@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-3.0.0.tgz#302b25f55f674854dce65c2532d98919b118a408" + integrity sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA== + +"@google-cloud/promisify@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-3.0.1.tgz#8d724fb280f47d1ff99953aee0c1669b25238c2e" + integrity sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA== + +"@google-cloud/storage@^6.9.3": + version "6.11.0" + resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-6.11.0.tgz#7217dd06184e609d1c444b7c930d76c6cffeb634" + integrity sha512-p5VX5K2zLTrMXlKdS1CiQNkKpygyn7CBFm5ZvfhVj6+7QUsjWvYx9YDMkYXdarZ6JDt4cxiu451y9QUIH82ZTw== + dependencies: + "@google-cloud/paginator" "^3.0.7" + "@google-cloud/projectify" "^3.0.0" + "@google-cloud/promisify" "^3.0.0" + abort-controller "^3.0.0" + async-retry "^1.3.3" + compressible "^2.0.12" + duplexify "^4.0.0" + ent "^2.2.0" + extend "^3.0.2" + gaxios "^5.0.0" + google-auth-library "^8.0.1" + mime "^3.0.0" + mime-types "^2.0.8" + p-limit "^3.0.1" + retry-request "^5.0.0" + teeny-request "^8.0.0" + uuid "^8.0.0" + +"@humanwhocodes/config-array@^0.11.10": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" - minimatch "^3.0.4" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== "@humanwhocodes/object-schema@^1.2.1": version "1.2.1" @@ -541,29 +604,63 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" - integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.11" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" - integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.0": - version "0.3.4" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" - integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" "@js-joda/core@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-2.0.0.tgz#e9a351ee6feb91262770e2a3d085aa0219ad6afb" integrity sha512-OWm/xa9O9e4ugzNHoRT3IsXZZYfaV6Ia1aRwctOmCQ2GYWMnhKBzMC1WomqCh/oGxEZKNtPy5xv5//VIAOgMqw== +"@mapbox/node-pre-gyp@^1.0.0": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c" + integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA== + dependencies: + detect-libc "^2.0.0" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.7" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -577,7 +674,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -629,9 +726,9 @@ integrity sha512-3BGrt6FLjqM6br5AhWRKTr3u5GIVkjRYeAFrMp3HjnfICrg4xOrVRwFavKT6tsp++bq5dluL5t8ME/Nha/6c1Q== "@npmcli/config@^2.3.0": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@npmcli/config/-/config-2.3.2.tgz#6027efc132fcc809abef749c2f2e13dc4dcd6e0b" - integrity sha512-2/9dj143BFgQR8qxJbYptd8k+4+Po2uHYq3H6498ynZcRu4LrsDlngov5HGrvo2+f0pe0fBJwDEP2rRtaW8bkw== + version "2.4.0" + resolved "https://registry.yarnpkg.com/@npmcli/config/-/config-2.4.0.tgz#1447b0274f9502871dabd3ab1d8302472d515b1f" + integrity sha512-fwxu/zaZnvBJohXM3igzqa3P1IVYWi5N343XcKvKkJbAx+rTqegS5tAul4NLiMPQh6WoS5a4er6oo/ieUx1f4g== dependencies: ini "^2.0.0" mkdirp-infer-owner "^2.0.0" @@ -744,19 +841,37 @@ dependencies: "@octokit/types" "^6.0.3" +"@octokit/auth-token@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.4.tgz#70e941ba742bdd2b49bdb7393e821dea8520a3db" + integrity sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ== + "@octokit/core@^3.5.1": - version "3.5.1" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.5.1.tgz#8601ceeb1ec0e1b1b8217b960a413ed8e947809b" - integrity sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085" + integrity sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q== dependencies: "@octokit/auth-token" "^2.4.4" "@octokit/graphql" "^4.5.8" - "@octokit/request" "^5.6.0" + "@octokit/request" "^5.6.3" "@octokit/request-error" "^2.0.5" "@octokit/types" "^6.0.3" before-after-hook "^2.2.0" universal-user-agent "^6.0.0" +"@octokit/core@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.2.1.tgz#fee6341ad0ce60c29cc455e056cd5b500410a588" + integrity sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw== + dependencies: + "@octokit/auth-token" "^3.0.0" + "@octokit/graphql" "^5.0.0" + "@octokit/request" "^6.0.0" + "@octokit/request-error" "^3.0.0" + "@octokit/types" "^9.0.0" + before-after-hook "^2.2.0" + universal-user-agent "^6.0.0" + "@octokit/endpoint@^6.0.1": version "6.0.12" resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658" @@ -766,6 +881,15 @@ is-plain-object "^5.0.0" universal-user-agent "^6.0.0" +"@octokit/endpoint@^7.0.0": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-7.0.6.tgz#791f65d3937555141fb6c08f91d618a7d645f1e2" + integrity sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg== + dependencies: + "@octokit/types" "^9.0.0" + is-plain-object "^5.0.0" + universal-user-agent "^6.0.0" + "@octokit/graphql@^4.5.8": version "4.8.0" resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3" @@ -775,17 +899,39 @@ "@octokit/types" "^6.0.3" universal-user-agent "^6.0.0" -"@octokit/openapi-types@^11.2.0": - version "11.2.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-11.2.0.tgz#b38d7fc3736d52a1e96b230c1ccd4a58a2f400a6" - integrity sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA== +"@octokit/graphql@^5.0.0": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-5.0.6.tgz#9eac411ac4353ccc5d3fca7d76736e6888c5d248" + integrity sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw== + dependencies: + "@octokit/request" "^6.0.0" + "@octokit/types" "^9.0.0" + universal-user-agent "^6.0.0" + +"@octokit/openapi-types@^12.11.0": + version "12.11.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0" + integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ== + +"@octokit/openapi-types@^18.0.0": + version "18.0.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-18.0.0.tgz#f43d765b3c7533fd6fb88f3f25df079c24fccf69" + integrity sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw== "@octokit/plugin-paginate-rest@^2.16.8": - version "2.17.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz#32e9c7cab2a374421d3d0de239102287d791bce7" - integrity sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw== + version "2.21.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz#7f12532797775640dbb8224da577da7dc210c87e" + integrity sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw== dependencies: - "@octokit/types" "^6.34.0" + "@octokit/types" "^6.40.0" + +"@octokit/plugin-paginate-rest@^6.1.2": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz#f86456a7a1fe9e58fec6385a85cf1b34072341f8" + integrity sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ== + dependencies: + "@octokit/tsconfig" "^1.0.2" + "@octokit/types" "^9.2.3" "@octokit/plugin-request-log@^1.0.4": version "1.0.4" @@ -793,13 +939,29 @@ integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== "@octokit/plugin-rest-endpoint-methods@^5.12.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz#8c46109021a3412233f6f50d28786f8e552427ba" - integrity sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA== + version "5.16.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz#7ee8bf586df97dd6868cf68f641354e908c25342" + integrity sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw== dependencies: - "@octokit/types" "^6.34.0" + "@octokit/types" "^6.39.0" deprecation "^2.3.1" +"@octokit/plugin-retry@^4.1.3": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@octokit/plugin-retry/-/plugin-retry-4.1.6.tgz#e33b1e520f0bd24d515c9901676b55df64dfc795" + integrity sha512-obkYzIgEC75r8+9Pnfiiqy3y/x1bc3QLE5B7qvv9wi9Kj0R5tGQFC6QMBg1154WQ9lAVypuQDGyp3hNpp15gQQ== + dependencies: + "@octokit/types" "^9.0.0" + bottleneck "^2.15.3" + +"@octokit/plugin-throttling@^5.2.3": + version "5.2.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-throttling/-/plugin-throttling-5.2.3.tgz#9f552a14dcee5c7326dd9dee64a71ea76b108814" + integrity sha512-C9CFg9mrf6cugneKiaI841iG8DOv6P5XXkjmiNNut+swePxQ7RWEdAZRp5rJoE1hjsIqiYcKa/ZkOQ+ujPI39Q== + dependencies: + "@octokit/types" "^9.0.0" + bottleneck "^2.15.3" + "@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677" @@ -809,7 +971,16 @@ deprecation "^2.0.0" once "^1.4.0" -"@octokit/request@^5.6.0": +"@octokit/request-error@^3.0.0": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-3.0.3.tgz#ef3dd08b8e964e53e55d471acfe00baa892b9c69" + integrity sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ== + dependencies: + "@octokit/types" "^9.0.0" + deprecation "^2.0.0" + once "^1.4.0" + +"@octokit/request@^5.6.0", "@octokit/request@^5.6.3": version "5.6.3" resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A== @@ -821,7 +992,19 @@ node-fetch "^2.6.7" universal-user-agent "^6.0.0" -"@octokit/rest@^18.0.0", "@octokit/rest@^18.12.0": +"@octokit/request@^6.0.0": + version "6.2.6" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-6.2.6.tgz#ff8f503c690f84e3ebd33d2d43e63c0a27ac50e0" + integrity sha512-T/waXf/xjie8Qn5IyFYAcI/HXvw9SPkcQWErGP9H471IWRDRCN+Gn/QOptPMAZRT4lJb2bLHxQfCXjU0mJRyng== + dependencies: + "@octokit/endpoint" "^7.0.0" + "@octokit/request-error" "^3.0.0" + "@octokit/types" "^9.0.0" + is-plain-object "^5.0.0" + node-fetch "^2.6.7" + universal-user-agent "^6.0.0" + +"@octokit/rest@^18.12.0": version "18.12.0" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.12.0.tgz#f06bc4952fc87130308d810ca9d00e79f6988881" integrity sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q== @@ -831,17 +1014,29 @@ "@octokit/plugin-request-log" "^1.0.4" "@octokit/plugin-rest-endpoint-methods" "^5.12.0" -"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.34.0": - version "6.34.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.34.0.tgz#c6021333334d1ecfb5d370a8798162ddf1ae8218" - integrity sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw== +"@octokit/tsconfig@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@octokit/tsconfig/-/tsconfig-1.0.2.tgz#59b024d6f3c0ed82f00d08ead5b3750469125af7" + integrity sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA== + +"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.34.0", "@octokit/types@^6.39.0", "@octokit/types@^6.40.0": + version "6.41.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04" + integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg== dependencies: - "@octokit/openapi-types" "^11.2.0" + "@octokit/openapi-types" "^12.11.0" + +"@octokit/types@^9.0.0", "@octokit/types@^9.2.3": + version "9.3.2" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-9.3.2.tgz#3f5f89903b69f6a2d196d78ec35f888c0013cac5" + integrity sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA== + dependencies: + "@octokit/openapi-types" "^18.0.0" "@opentelemetry/api@^1.0.1": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.0.3.tgz#13a12ae9e05c2a782f7b5e84c3cbfda4225eaf80" - integrity sha512-puWxACExDe9nxbBB3lOymQFrLYml2dVOrd7USiVRnSbgXE+KwBu+HxFvxrzfqsiSda9IWsXJG1ef7C1O2/GmKQ== + version "1.4.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" + integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== "@semantic-release/commit-analyzer@^9.0.2": version "9.0.2" @@ -856,36 +1051,32 @@ lodash "^4.17.4" micromatch "^4.0.2" -"@semantic-release/error@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@semantic-release/error/-/error-2.2.0.tgz#ee9d5a09c9969eade1ec864776aeda5c5cddbbf0" - integrity sha512-9Tj/qn+y2j+sjCI3Jd+qseGtHjOAeg7dU2/lVcqIQ9TV3QDaDXDYXcoOHU+7o2Hwh8L8ymL4gfuO7KxDs3q2zg== - "@semantic-release/error@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@semantic-release/error/-/error-3.0.0.tgz#30a3b97bbb5844d695eb22f9d3aa40f6a92770c2" integrity sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw== "@semantic-release/github@^8.0.0": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@semantic-release/github/-/github-8.0.2.tgz#80114a41f6ec8ab6c0d38a436b48ff3f2223ab16" - integrity sha512-wIbfhOeuxlYzMTjtSAa2xgr54n7ZuPAS2gadyTWBpUt2PNAPgla7A6XxCXJnaKPgfVF0iFfSk3B+KlVKk6ByVg== + version "8.1.0" + resolved "https://registry.yarnpkg.com/@semantic-release/github/-/github-8.1.0.tgz#c31fc5852d32975648445804d1984cd96e72c4d0" + integrity sha512-erR9E5rpdsz0dW1I7785JtndQuMWN/iDcemcptf67tBNOmBUN0b2YNOgcjYUnBpgRpZ5ozfBHrK7Bz+2ets/Dg== dependencies: - "@octokit/rest" "^18.0.0" - "@semantic-release/error" "^2.2.0" + "@octokit/core" "^4.2.1" + "@octokit/plugin-paginate-rest" "^6.1.2" + "@octokit/plugin-retry" "^4.1.3" + "@octokit/plugin-throttling" "^5.2.3" + "@semantic-release/error" "^3.0.0" aggregate-error "^3.0.0" - bottleneck "^2.18.1" debug "^4.0.0" dir-glob "^3.0.0" - fs-extra "^10.0.0" + fs-extra "^11.0.0" globby "^11.0.0" - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.0" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.0" issue-parser "^6.0.0" lodash "^4.17.4" mime "^3.0.0" p-filter "^2.0.0" - p-retry "^4.0.0" url-join "^4.0.0" "@semantic-release/npm@^8.0.0": @@ -924,18 +1115,32 @@ read-pkg-up "^7.0.0" "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.3": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" - integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + version "1.8.6" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" + integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^7.0.4", "@sinonjs/fake-timers@^7.1.0": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5" - integrity sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg== +"@sinonjs/commons@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3" + integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg== dependencies: - "@sinonjs/commons" "^1.7.0" + type-detect "4.0.8" + +"@sinonjs/commons@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" + integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz#b3e322a34c5f26e3184e7f6115695f299c1b1194" + integrity sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg== + dependencies: + "@sinonjs/commons" "^3.0.0" "@sinonjs/fake-timers@^8.1.0": version "8.1.0" @@ -945,18 +1150,29 @@ "@sinonjs/commons" "^1.7.0" "@sinonjs/samsam@^6.0.2": - version "6.0.2" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-6.0.2.tgz#a0117d823260f282c04bff5f8704bdc2ac6910bb" - integrity sha512-jxPRPp9n93ci7b8hMfJOFDPRLFYadN6FSpeROFTR4UNF4i5b+EK6m4QXPO46BDhFgRy1JuS87zAnFOzCUwMJcQ== + version "6.1.3" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-6.1.3.tgz#4e30bcd4700336363302a7d72cbec9b9ab87b104" + integrity sha512-nhOb2dWPeb1sd3IQXL/dVPnKHDOAFfvichtBf4xV00/rU1QbPCQqKMbvIheIjqwVjh7qIgf2AHTHi391yMOMpQ== dependencies: "@sinonjs/commons" "^1.6.0" lodash.get "^4.4.2" type-detect "^4.0.8" "@sinonjs/text-encoding@^0.7.1": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" - integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== + version "0.7.2" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" + integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== + +"@techteamer/ocsp@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@techteamer/ocsp/-/ocsp-1.0.0.tgz#7b82b02093fbe351e915bb37685ac1ac5a1233d3" + integrity sha512-lNAOoFHaZN+4huo30ukeqVrUmfC+avoEBYQ11QAnAw1PFhnI5oBCg8O/TNiCoEWix7gNGBIEjrQwtPREqKMPog== + dependencies: + asn1.js "^5.4.1" + asn1.js-rfc2560 "^5.0.1" + asn1.js-rfc5280 "^3.0.0" + async "^3.2.1" + simple-lru-cache "^0.0.2" "@tootallnate/once@1": version "1.1.2" @@ -969,31 +1185,31 @@ integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== "@types/chai@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" - integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== + version "4.3.5" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" + integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== -"@types/debug@^4.1.7": - version "4.1.7" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" - integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== +"@types/debug@^4.1.8": + version "4.1.8" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.8.tgz#cef723a5d0a90990313faec2d1e22aee5eecb317" + integrity sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ== dependencies: "@types/ms" "*" -"@types/geojson@^7946.0.7": - version "7946.0.8" - resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca" - integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA== +"@types/geojson@^7946.0.8": + version "7946.0.10" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.10.tgz#6dfbf5ea17142f7f9a043809f1cd4c448cb68249" + integrity sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA== "@types/json-schema@^7.0.9": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== -"@types/lodash@4.14.182": - version "4.14.182" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" - integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== +"@types/lodash@4.14.197": + version "4.14.197" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.197.tgz#e95c5ddcc814ec3e84c891910a01e0c8a378c54b" + integrity sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g== "@types/minimist@^1.2.0": version "1.2.2" @@ -1001,9 +1217,9 @@ integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== "@types/mocha@^9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.0.0.tgz#3205bcd15ada9bc681ac20bef64e9e6df88fd297" - integrity sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA== + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== "@types/ms@*": version "0.7.31" @@ -1011,27 +1227,27 @@ integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== "@types/node-fetch@^2.5.0": - version "2.6.1" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.1.tgz#8f127c50481db65886800ef496f20bbf15518975" - integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA== + version "2.6.4" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" + integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== dependencies: "@types/node" "*" form-data "^3.0.0" "@types/node@*": - version "17.0.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" - integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== - -"@types/node@^14.14.28": - version "14.17.34" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.34.tgz#fe4b38b3f07617c0fa31ae923fca9249641038f0" - integrity sha512-USUftMYpmuMzeWobskoPfzDi+vkpe0dvcOBRNOscFrGxVp4jomnRxWuVohgqBow2xyIPC0S3gjxV/5079jhmDg== + version "20.3.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.1.tgz#e8a83f1aa8b649377bb1fb5d7bac5cb90e784dfe" + integrity sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg== "@types/node@^16.11.17": - version "16.11.17" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.17.tgz#ae146499772e33fc6382e1880bc567e41a528586" - integrity sha512-C1vTZME8cFo8uxY2ui41xcynEotVkczIVI5AjLmy5pkpBv/FtG+jhtOlfcPysI8VRVwoOMv6NJm44LGnoMSWkw== + version "16.18.36" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.36.tgz#0db5d7efc4760d36d0d1d22c85d1a53accd5dc27" + integrity sha512-8egDX8dE50XyXWH6C6PRCNkTP106DuUrvdrednFouDSmCi7IOvrqr0frznfZaHifHH/3aq/7a7v9N4wdXMqhBQ== + +"@types/node@^17.0.10": + version "17.0.45" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" + integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== "@types/node@^8.0.47": version "8.10.66" @@ -1048,17 +1264,27 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== -"@types/retry@^0.12.0": - version "0.12.1" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" - integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== +"@types/semver@^7.3.12": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== "@types/sinon@^10.0.6": - version "10.0.6" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.6.tgz#bc3faff5154e6ecb69b797d311b7cf0c1b523a1d" - integrity sha512-6EF+wzMWvBNeGrfP3Nx60hhx+FfwSg1JJBLAAP/IdIUq0EYkqCYf70VT3PhuhPX9eLD+Dp+lNdpb/ZeHG8Yezg== + version "10.0.15" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.15.tgz#513fded9c3cf85e589bbfefbf02b2a0541186b48" + integrity sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ== dependencies: - "@sinonjs/fake-timers" "^7.1.0" + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" + integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== + +"@types/triple-beam@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.2.tgz#38ecb64f01aa0d02b7c8f4222d7c38af6316fef8" + integrity sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g== "@types/tunnel@^0.0.3": version "0.0.3" @@ -1067,90 +1293,94 @@ dependencies: "@types/node" "*" -"@types/validator@^13.7.1": - version "13.7.1" - resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.1.tgz#cdab1b4779f6b1718a08de89d92d2603b71950cb" - integrity sha512-I6OUIZ5cYRk5lp14xSOAiXjWrfVoMZVjDuevBYgQDYzZIjsf2CAISpEcXOkFAtpAHbmWIDLcZObejqny/9xq5Q== +"@types/validator@^13.7.17": + version "13.7.17" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.17.tgz#0a6d1510395065171e3378a4afc587a3aefa7cc1" + integrity sha512-aqayTNmeWrZcvnG2MG9eGYI6b7S5fl+yKgPs6bAjOTwPS316R5SxBGKvtSExfyoJU7pIeHJfsHI0Ji41RVMkvQ== "@typescript-eslint/eslint-plugin@^5.8.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.12.1.tgz#b2cd3e288f250ce8332d5035a2ff65aba3374ac4" - integrity sha512-M499lqa8rnNK7mUv74lSFFttuUsubIRdAbHcVaP93oFcKkEmHmLqy2n7jM9C8DVmFMYK61ExrZU6dLYhQZmUpw== - dependencies: - "@typescript-eslint/scope-manager" "5.12.1" - "@typescript-eslint/type-utils" "5.12.1" - "@typescript-eslint/utils" "5.12.1" - debug "^4.3.2" - functional-red-black-tree "^1.0.1" - ignore "^5.1.8" - regexpp "^3.2.0" - semver "^7.3.5" + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.11.tgz#8d466aa21abea4c3f37129997b198d141f09e76f" + integrity sha512-XxuOfTkCUiOSyBWIvHlUraLw/JT/6Io1365RO6ZuI88STKMavJZPNMU0lFcUTeQXEhHiv64CbxYxBNoDVSmghg== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.59.11" + "@typescript-eslint/type-utils" "5.59.11" + "@typescript-eslint/utils" "5.59.11" + debug "^4.3.4" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" tsutils "^3.21.0" "@typescript-eslint/parser@^5.8.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.12.1.tgz#b090289b553b8aa0899740d799d0f96e6f49771b" - integrity sha512-6LuVUbe7oSdHxUWoX/m40Ni8gsZMKCi31rlawBHt7VtW15iHzjbpj2WLiToG2758KjtCCiLRKZqfrOdl3cNKuw== - dependencies: - "@typescript-eslint/scope-manager" "5.12.1" - "@typescript-eslint/types" "5.12.1" - "@typescript-eslint/typescript-estree" "5.12.1" - debug "^4.3.2" - -"@typescript-eslint/scope-manager@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.12.1.tgz#58734fd45d2d1dec49641aacc075fba5f0968817" - integrity sha512-J0Wrh5xS6XNkd4TkOosxdpObzlYfXjAFIm9QxYLCPOcHVv1FyyFCPom66uIh8uBr0sZCrtS+n19tzufhwab8ZQ== - dependencies: - "@typescript-eslint/types" "5.12.1" - "@typescript-eslint/visitor-keys" "5.12.1" - -"@typescript-eslint/type-utils@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.12.1.tgz#8d58c6a0bb176b5e9a91581cda1a7f91a114d3f0" - integrity sha512-Gh8feEhsNLeCz6aYqynh61Vsdy+tiNNkQtc+bN3IvQvRqHkXGUhYkUi+ePKzP0Mb42se7FDb+y2SypTbpbR/Sg== - dependencies: - "@typescript-eslint/utils" "5.12.1" - debug "^4.3.2" + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.11.tgz#af7d4b7110e3068ce0b97550736de455e4250103" + integrity sha512-s9ZF3M+Nym6CAZEkJJeO2TFHHDsKAM3ecNkLuH4i4s8/RCPnF5JRip2GyviYkeEAcwGMJxkqG9h2dAsnA1nZpA== + dependencies: + "@typescript-eslint/scope-manager" "5.59.11" + "@typescript-eslint/types" "5.59.11" + "@typescript-eslint/typescript-estree" "5.59.11" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.11.tgz#5d131a67a19189c42598af9fb2ea1165252001ce" + integrity sha512-dHFOsxoLFtrIcSj5h0QoBT/89hxQONwmn3FOQ0GOQcLOOXm+MIrS8zEAhs4tWl5MraxCY3ZJpaXQQdFMc2Tu+Q== + dependencies: + "@typescript-eslint/types" "5.59.11" + "@typescript-eslint/visitor-keys" "5.59.11" + +"@typescript-eslint/type-utils@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.11.tgz#5eb67121808a84cb57d65a15f48f5bdda25f2346" + integrity sha512-LZqVY8hMiVRF2a7/swmkStMYSoXMFlzL6sXV6U/2gL5cwnLWQgLEG8tjWPpaE4rMIdZ6VKWwcffPlo1jPfk43g== + dependencies: + "@typescript-eslint/typescript-estree" "5.59.11" + "@typescript-eslint/utils" "5.59.11" + debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.12.1.tgz#46a36a28ff4d946821b58fe5a73c81dc2e12aa89" - integrity sha512-hfcbq4qVOHV1YRdhkDldhV9NpmmAu2vp6wuFODL71Y0Ixak+FLeEU4rnPxgmZMnGreGEghlEucs9UZn5KOfHJA== +"@typescript-eslint/types@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.11.tgz#1a9018fe3c565ba6969561f2a49f330cf1fe8db1" + integrity sha512-epoN6R6tkvBYSc+cllrz+c2sOFWkbisJZWkOE+y3xHtvYaOE6Wk6B8e114McRJwFRjGvYdJwLXQH5c9osME/AA== -"@typescript-eslint/typescript-estree@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.12.1.tgz#6a9425b9c305bcbc38e2d1d9a24c08e15e02b722" - integrity sha512-ahOdkIY9Mgbza7L9sIi205Pe1inCkZWAHE1TV1bpxlU4RZNPtXaDZfiiFWcL9jdxvW1hDYZJXrFm+vlMkXRbBw== +"@typescript-eslint/typescript-estree@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.11.tgz#b2caaa31725e17c33970c1197bcd54e3c5f42b9f" + integrity sha512-YupOpot5hJO0maupJXixi6l5ETdrITxeo5eBOeuV7RSKgYdU3G5cxO49/9WRnJq9EMrB7AuTSLH/bqOsXi7wPA== dependencies: - "@typescript-eslint/types" "5.12.1" - "@typescript-eslint/visitor-keys" "5.12.1" - debug "^4.3.2" - globby "^11.0.4" + "@typescript-eslint/types" "5.59.11" + "@typescript-eslint/visitor-keys" "5.59.11" + debug "^4.3.4" + globby "^11.1.0" is-glob "^4.0.3" - semver "^7.3.5" + semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.12.1.tgz#447c24a05d9c33f9c6c64cb48f251f2371eef920" - integrity sha512-Qq9FIuU0EVEsi8fS6pG+uurbhNTtoYr4fq8tKjBupsK5Bgbk2I32UGm0Sh+WOyjOPgo/5URbxxSNV6HYsxV4MQ== +"@typescript-eslint/utils@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.11.tgz#9dbff49dc80bfdd9289f9f33548f2e8db3c59ba1" + integrity sha512-didu2rHSOMUdJThLk4aZ1Or8IcO3HzCw/ZvEjTTIfjIrcdd5cvSIwwDy2AOlE7htSNp7QIZ10fLMyRCveesMLg== dependencies: + "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.12.1" - "@typescript-eslint/types" "5.12.1" - "@typescript-eslint/typescript-estree" "5.12.1" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.59.11" + "@typescript-eslint/types" "5.59.11" + "@typescript-eslint/typescript-estree" "5.59.11" eslint-scope "^5.1.1" - eslint-utils "^3.0.0" + semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.12.1": - version "5.12.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.12.1.tgz#f722da106c8f9695ae5640574225e45af3e52ec3" - integrity sha512-l1KSLfupuwrXx6wc0AuOmC7Ko5g14ZOQ86wJJqRbdLbXLK02pK/DPiDDqCc7BqqiiA04/eAA6ayL0bgOrAkH7A== +"@typescript-eslint/visitor-keys@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.11.tgz#dca561ddad169dc27d62396d64f45b2d2c3ecc56" + integrity sha512-KGYniTGG3AMTuKF9QBD7EIrvufkB6O6uX3knP73xbKLMpH+QRPcgnCxjWXSHjMRuOxFLovljqQgQpR0c7GvjoA== dependencies: - "@typescript-eslint/types" "5.12.1" - eslint-visitor-keys "^3.0.0" + "@typescript-eslint/types" "5.59.11" + eslint-visitor-keys "^3.3.0" JSONStream@^1.0.4: version "1.3.5" @@ -1163,44 +1393,51 @@ JSONStream@^1.0.4: abab@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" - integrity sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4= + integrity sha512-I+Wi+qiE2kUXyrRhNsWv6XsjUTBJjSoVSctKNBfLG5zG/Xe7Rjbxf13+vqYHNTwHaFU+FtSlVxOCTiMEVtPv0A== abbrev@1, abbrev@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + acorn-globals@^1.0.4: version "1.0.9" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf" - integrity sha1-VbtemGkVB7dFedBRNBMhfDgMVM8= + integrity sha512-j3/4pkfih8W4NK22gxVSXcEonTpAHOHh0hu5BoZrKcOsW/4oBPxTi4Yk3SAj+FhC1f3+bRTkXdm4019gw1vg9g== dependencies: acorn "^2.1.0" -acorn-jsx@^5.3.1: +acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== +acorn-walk@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + acorn@^2.1.0, acorn@^2.4.0: version "2.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" - integrity sha1-q259nYhqrKiwhbwzEreaGYQz8Oc= - -acorn@^8.6.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" - integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== + integrity sha512-pXK8ez/pVjqFdAgBkF1YPVRacuLQ9EXBKaKWaeh58WNfMkCmZhOZzu+NtKSPD5PHmCCHheQ5cD29qM1K4QTxIg== -acorn@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== +acorn@^8.7.0, acorn@^8.8.0: + version "8.9.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" + integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== adal-node@^0.1.28: version "0.1.28" resolved "https://registry.yarnpkg.com/adal-node/-/adal-node-0.1.28.tgz#468c4bb3ebbd96b1270669f4b9cba4e0065ea485" - integrity sha1-RoxLs+u9lrEnBmn0ucuk4AZepIU= + integrity sha512-98nQ5MQSyJR0ZY/R0Mue/cv4OkebRyKz4hS40GdkZU42Bq49ldHeup7UeAo/0vROMB57CX2et6IF0U/Pe1rY3A== dependencies: "@types/node" "^8.0.47" async ">=0.6.0" @@ -1212,27 +1449,27 @@ adal-node@^0.1.28: xmldom ">= 0.1.x" xpath.js "~1.1.0" -agent-base@6, agent-base@^6.0.2: +agent-base@6, agent-base@^6.0.0, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" -agent-base@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" - integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== +agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" + integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== dependencies: - es6-promisify "^5.0.0" + debug "^4.3.4" agentkeepalive@^4.1.3: - version "4.2.1" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" - integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.3.0.tgz#bb999ff07412653c1803b3ced35e50729830a255" + integrity sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg== dependencies: debug "^4.1.0" - depd "^1.1.2" + depd "^2.0.0" humanize-ms "^1.2.1" aggregate-error@^3.0.0: @@ -1258,11 +1495,6 @@ ansi-colors@3.2.3: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== -ansi-colors@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - ansi-escapes@^4.3.0, ansi-escapes@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -1273,17 +1505,17 @@ ansi-escapes@^4.3.0, ansi-escapes@^4.3.1: ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== ansi-regex@^5.0.1: version "5.0.1" @@ -1298,7 +1530,7 @@ ansi-regex@^6.0.1: ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" @@ -1315,24 +1547,29 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^4.3.0: color-convert "^2.0.1" ansi-styles@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.0.tgz#87313c102b8118abd57371afab34618bf7350ed3" - integrity sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ== + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== ansicolors@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" - integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= + integrity sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg== ansistyles@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539" - integrity sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk= + integrity sha512-6QWEyvMgIXX0eO972y7YPBLSBsq7UWKFAoNNTLGaOJ9bstcEL9sCbcjf96dVfNDdUsRoGOK82vWFJlKApXds7g== + +any-promise@^1.0.0, any-promise@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== anymatch@~3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -1340,7 +1577,7 @@ anymatch@~3.1.1: append-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" - integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= + integrity sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA== dependencies: buffer-equal "^1.0.0" @@ -1364,7 +1601,7 @@ aproba@^1.0.3: archy@^1.0.0, archy@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== are-we-there-yet@^2.0.0: version "2.0.0" @@ -1374,6 +1611,14 @@ are-we-there-yet@^2.0.0: delegates "^1.0.0" readable-stream "^3.6.0" +are-we-there-yet@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" + integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + are-we-there-yet@~1.1.2: version "1.1.7" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" @@ -1402,49 +1647,59 @@ argparse@^2.0.1: argv-formatter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/argv-formatter/-/argv-formatter-1.0.0.tgz#a0ca0cbc29a5b73e836eebe1cbf6c5e0e4eb82f9" - integrity sha1-oMoMvCmltz6Dbuvhy/bF4OTrgvk= + integrity sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw== + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" array-ify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" - integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= + integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array.prototype.reduce@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" + integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + +arrify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== asap@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== -asn1.js-rfc2560@^4.0.0: - version "4.0.6" - resolved "https://registry.yarnpkg.com/asn1.js-rfc2560/-/asn1.js-rfc2560-4.0.6.tgz#0975ce84768a8401e95884ad13e2d00e7b25a280" - integrity sha512-ysf48ni+f/efNPilq4+ApbifUPcSW/xbDeQAh055I+grr2gXgNRQqHew7kkO70WSMQ2tEOURVwsK+dJqUNjIIg== - dependencies: - asn1.js-rfc5280 "^2.0.0" - -asn1.js-rfc2560@^5.0.0: +asn1.js-rfc2560@^5.0.0, asn1.js-rfc2560@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/asn1.js-rfc2560/-/asn1.js-rfc2560-5.0.1.tgz#cff99b903e714756b29503ad49de01c72f131e60" integrity sha512-1PrVg6kuBziDN3PGFmRk3QrjpKvP9h/Hv5yMrFZvC1kpzP6dQRzf5BpKstANqHBkaOUmTpakJWhicTATOA/SbA== dependencies: asn1.js-rfc5280 "^3.0.0" -asn1.js-rfc5280@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/asn1.js-rfc5280/-/asn1.js-rfc5280-2.0.1.tgz#072f3dfc03f86d1faae7485c6197584ba2bb5ddc" - integrity sha512-1e2ypnvTbYD/GdxWK77tdLBahvo1fZUHlQJqAVUuZWdYj0rdjGcf2CWYUtbsyRYpYUMwMWLZFUtLxog8ZXTrcg== - dependencies: - asn1.js "^4.5.0" - asn1.js-rfc5280@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/asn1.js-rfc5280/-/asn1.js-rfc5280-3.0.0.tgz#94e60498d5d4984b842d1a825485837574ccc902" @@ -1452,16 +1707,7 @@ asn1.js-rfc5280@^3.0.0: dependencies: asn1.js "^5.0.0" -asn1.js@^4.5.0, asn1.js@^4.8.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -asn1.js@^5.0.0: +asn1.js@^5.0.0, asn1.js@^5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== @@ -1481,13 +1727,20 @@ asn1@~0.2.3: assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== +ast-types@^0.13.2: + version "0.13.4" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" + integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== + dependencies: + tslib "^2.0.1" + astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -1500,30 +1753,32 @@ async-hook-jl@^1.7.6: dependencies: stack-chain "^1.3.7" -async@>=0.6.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.2.tgz#2eb7671034bb2194d45d30e31e24ec7e7f9670cd" - integrity sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g== - -async@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= +async-retry@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" + integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== + dependencies: + retry "0.13.1" -async@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" - integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g== +async@>=0.6.0, async@^3.2.1, async@^3.2.3: + version "3.2.4" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== aws-sdk@^2.878.0: - version "2.1080.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1080.0.tgz#90aca78e159f8ad04fb77fc6740a54ec0981b977" - integrity sha512-CI3ovrQ7WarYuSliDCihpA5w+LoBWEvgBayRMgrZzGmAIEP9pNtXYWQ/wSjVYOyYtU1ilOFyhQBNExX3Kz1pXw== + version "2.1398.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1398.0.tgz#8627ff0e8b39d656dd9b8eeabc6699fdfe0f4d0a" + integrity sha512-jiHAhKPPKDHZdwsbY9FD/WfX9RfQ7+7eKvXyXr7BYf0JIShok4TWan/iLdNWCtU0BhXYl+bfG9W0pG4rwJ9Ivg== dependencies: buffer "4.9.2" events "1.1.1" @@ -1532,30 +1787,46 @@ aws-sdk@^2.878.0: querystring "0.2.0" sax "1.2.1" url "0.10.3" - uuid "3.3.2" - xml2js "0.4.19" + util "^0.12.4" + uuid "8.0.0" + xml2js "0.5.0" aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== -axios@^0.21.1, axios@^0.21.4: +axios@^0.21.1: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: follow-redirects "^1.14.0" +axios@^0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" + integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== + dependencies: + follow-redirects "^1.14.8" + +axios@^0.27.2: + version "0.27.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" + integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== + dependencies: + follow-redirects "^1.14.9" + form-data "^4.0.0" + babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== dependencies: chalk "^1.1.3" esutils "^2.0.2" @@ -1564,7 +1835,7 @@ babel-code-frame@^6.26.0: babel-generator@6.11.4: version "6.11.4" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.11.4.tgz#14f6933abb20c62666d27e3b7b9f5b9dc0712a9a" - integrity sha1-FPaTOrsgxiZm0n47e59bncBxKpo= + integrity sha512-JFBWXdE89s4V3E8kZroEEsnQF2A4/+55IzciGjnAATXj7HTMSum3SrW7QRYGSDLWTTQF+hhD3BmC2UFGgtM0Yw== dependencies: babel-messages "^6.8.0" babel-runtime "^6.9.0" @@ -1590,14 +1861,14 @@ babel-generator@6.26.1: babel-messages@^6.23.0, babel-messages@^6.8.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= + integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== dependencies: babel-runtime "^6.22.0" babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.9.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== dependencies: core-js "^2.4.0" regenerator-runtime "^0.11.0" @@ -1605,7 +1876,7 @@ babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.9.0: babel-traverse@6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= + integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== dependencies: babel-code-frame "^6.26.0" babel-messages "^6.23.0" @@ -1620,7 +1891,7 @@ babel-traverse@6.26.0: babel-types@^6.10.2, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== dependencies: babel-runtime "^6.26.0" esutils "^2.0.2" @@ -1637,7 +1908,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.0.2: +base64-js@^1.0.2, base64-js@^1.3.0: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -1645,14 +1916,19 @@ base64-js@^1.0.2: bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== dependencies: tweetnacl "^0.14.3" before-after-hook@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" - integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== + version "2.2.3" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" + integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== + +better-eval@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/better-eval/-/better-eval-1.3.0.tgz#a957cabcb50b6b0e40620136acaf8e06806d95d0" + integrity sha512-rQdKZHTWok2uC3wHyGwoV6mOxhnOyp07iHhyWQlS+U5zkYyhOEOT6Ri4Q0vPThTqCYs6RCbtAfTbPG+lUZkocw== big-integer@^1.6.17, big-integer@^1.6.43, big-integer@^1.6.51: version "1.6.51" @@ -1662,7 +1938,12 @@ big-integer@^1.6.17, big-integer@^1.6.43, big-integer@^1.6.51: bignumber.js@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8" - integrity sha1-g4qZLan51zfg9LLbC+YrsJ3Qxeg= + integrity sha512-uw4ra6Cv483Op/ebM0GBKKfxZlSmn6NgFRby5L3yGTlunLj53KQgndDlqy2WVFOwgvurocApYkSud0aO+mvrpQ== + +bignumber.js@^9.0.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" + integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== bin-links@^2.2.1: version "2.3.0" @@ -1684,7 +1965,7 @@ binary-extensions@^2.0.0, binary-extensions@^2.2.0: binary@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" - integrity sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk= + integrity sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg== dependencies: buffers "~0.1.1" chainsaw "~0.1.0" @@ -1692,7 +1973,7 @@ binary@~0.3.0: binascii@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/binascii/-/binascii-0.0.2.tgz#a7f8a8801dbccf8b1756b743daa0fee9e2d9e0ee" - integrity sha1-p/iogB28z4sXVrdD2qD+6eLZ4O4= + integrity sha512-rA2CrUl1+6yKrn+XgLs8Hdy18OER1UW146nM+ixzhQXDY+Bd3ySkyIJGwF2a4I45JwbvF1mDL/nWkqBwpOcdBA== bindings@^1.5.0: version "1.5.0" @@ -1719,19 +2000,24 @@ bl@^3.0.0: bluebird@~3.4.1: version "3.4.7" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" - integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM= + integrity sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA== bn.js@^4.0.0: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + boolbase@^1.0.0, boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -bottleneck@^2.18.1: +bottleneck@^2.15.3: version "2.19.5" resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== @@ -1744,7 +2030,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1754,23 +2040,22 @@ braces@^3.0.1, braces@~3.0.2: browser-request@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/browser-request/-/browser-request-0.3.3.tgz#9ece5b5aca89a29932242e18bf933def9876cc17" - integrity sha1-ns5bWsqJopkyJC4Yv5M975h2zBc= + integrity sha512-YyNI4qJJ+piQG6MMEuo7J3Bzaqssufx04zpEKYfSrl/1Op59HWali9zMtBpXnkmqMcOuWJPZvudrm9wISmnCbg== browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -browserslist@^4.17.5: - version "4.19.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.3.tgz#29b7caad327ecf2859485f696f9604214bedd383" - integrity sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg== +browserslist@^4.21.3: + version "4.21.9" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635" + integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg== dependencies: - caniuse-lite "^1.0.30001312" - electron-to-chromium "^1.4.71" - escalade "^3.1.1" - node-releases "^2.0.2" - picocolors "^1.0.0" + caniuse-lite "^1.0.30001503" + electron-to-chromium "^1.4.431" + node-releases "^2.0.12" + update-browserslist-db "^1.0.11" buffer-alloc-unsafe@^1.1.0: version "1.1.0" @@ -1788,17 +2073,17 @@ buffer-alloc@^1.2.0: buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== buffer-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" - integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.1.tgz#2f7651be5b1b3f057fcd6e7ee16cf34767077d90" + integrity sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg== buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== buffer-from@^1.0.0: version "1.1.2" @@ -1827,12 +2112,17 @@ buffer@4.9.2: buffers@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" - integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s= + integrity sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ== builtins@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" - integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= + integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacache@^15.0.3, cacache@^15.0.5, cacache@^15.2.0, cacache@^15.3.0: version "15.3.0" @@ -1895,15 +2185,15 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@^1.0.30001312: - version "1.0.30001312" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" - integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== +caniuse-lite@^1.0.30001503: + version "1.0.30001503" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz#88b6ff1b2cf735f1f3361dc1a15b59f0561aa398" + integrity sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw== cardinal@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-2.1.1.tgz#7cc1055d822d212954d07b085dea251cc7bc5505" - integrity sha1-fMEFXYItISlU0HsIXeolHMe8VQU= + integrity sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw== dependencies: ansicolors "~0.3.2" redeyed "~2.1.0" @@ -1911,7 +2201,7 @@ cardinal@^2.1.1: caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== chai-as-promised@^7.1.1: version "7.1.1" @@ -1927,42 +2217,30 @@ chai-datetime@^1.8.0: dependencies: chai ">1.9.0" -chai@>1.9.0: - version "4.3.6" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" - integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== +chai@>1.9.0, chai@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== dependencies: assertion-error "^1.1.0" check-error "^1.0.2" - deep-eql "^3.0.1" + deep-eql "^4.1.2" get-func-name "^2.0.0" loupe "^2.3.1" pathval "^1.1.1" type-detect "^4.0.5" -chai@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" - integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - pathval "^1.1.1" - type-detect "^4.0.5" - chainsaw@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" - integrity sha1-XqtQsor+WAdNDVgpE4iCi15fvJg= + integrity sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ== dependencies: traverse ">=0.3.0 <0.4" chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -1990,23 +2268,24 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== -cheerio-select@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.5.0.tgz#faf3daeb31b17c5e1a9dabcee288aaf8aafa5823" - integrity sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg== +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== dependencies: - css-select "^4.1.3" - css-what "^5.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - domutils "^2.7.0" + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" cheerio@0.20.0: version "0.20.0" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.20.0.tgz#5c710f2bab95653272842ba01c6ea61b3545ec35" - integrity sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU= + integrity sha512-e5jCTzJc28MWkrLLjB1mu3ks7rDQJLC5y/JMdQkOAEX/dmJk62rC6Xae1yvOO4xyCxLpzcth3jIZ7nypmjQ/0w== dependencies: css-select "~1.2.0" dom-serializer "~0.1.0" @@ -2019,7 +2298,7 @@ cheerio@0.20.0: cheerio@0.22.0: version "0.22.0" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" - integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= + integrity sha512-8/MzidM6G/TgRelkzDG13y3Y9LxBjCb+8yOEZ9+wwq5gVF2w2pV0wmHvjfT0RvuxGyR7UEuK36r+yYMbT4uKgA== dependencies: css-select "~1.2.0" dom-serializer "~0.1.0" @@ -2041,7 +2320,7 @@ cheerio@0.22.0: cheerio@1.0.0-rc.2: version "1.0.0-rc.2" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" - integrity sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs= + integrity sha512-9LDHQy1jHc/eXMzPN6/oah9Qba4CjdKECC7YYEE/2zge/tsGwt19NQp5NFdfd5Lx6TZlyC5SXNQkG41P9r6XDg== dependencies: css-select "~1.2.0" dom-serializer "~0.1.0" @@ -2051,17 +2330,17 @@ cheerio@1.0.0-rc.2: parse5 "^3.0.1" cheerio@^1.0.0-rc.10: - version "1.0.0-rc.10" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e" - integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw== - dependencies: - cheerio-select "^1.5.0" - dom-serializer "^1.3.2" - domhandler "^4.2.0" - htmlparser2 "^6.1.0" - parse5 "^6.0.1" - parse5-htmlparser2-tree-adapter "^6.0.1" - tslib "^2.2.0" + version "1.0.0-rc.12" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" + integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== + dependencies: + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.0.1" + htmlparser2 "^8.0.1" + parse5 "^7.0.0" + parse5-htmlparser2-tree-adapter "^7.0.0" chokidar@3.3.0: version "3.3.0" @@ -2103,7 +2382,7 @@ clean-stack@^2.0.0: cli-columns@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-3.1.2.tgz#6732d972979efc2ae444a1f08e08fa139c96a18e" - integrity sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4= + integrity sha512-iQYpDgpPPmCjn534ikQOhi+ydP6uMar+DtJ6a0In4aGL/PKqWfao75s6eF81quQQaz7isGz+goNECLARRZswdg== dependencies: string-width "^2.0.0" strip-ansi "^3.0.1" @@ -2116,14 +2395,13 @@ cli-cursor@^3.1.0: restore-cursor "^3.1.0" cli-table3@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.0.tgz#b7b1bc65ca8e7b5cef9124e13dc2b21e2ce4faee" - integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ== + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== dependencies: - object-assign "^4.1.0" string-width "^4.2.0" optionalDependencies: - colors "^1.1.2" + "@colors/colors" "1.5.0" cli-truncate@^2.1.0: version "2.1.0" @@ -2168,25 +2446,34 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= + integrity sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g== clone-stats@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= + integrity sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag== clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== clone@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== cloneable-readable@^1.0.0: version "1.1.3" @@ -2216,7 +2503,7 @@ cmd-shim@^4.0.1: code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" @@ -2235,17 +2522,17 @@ color-convert@^2.0.1: color-logger@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/color-logger/-/color-logger-0.0.3.tgz#d9b22dd1d973e166b18bf313f9f481bba4df2018" - integrity sha1-2bIt0dlz4Waxi/MT+fSBu6TfIBg= + integrity sha512-s4oriek7VTdSmDbS5chJhNui3uUzlk/mU39V4HnOUv0KphRXpIj73lq4wY5f8l/x+WtHUhiV+FCzsrNO1w6REA== color-logger@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/color-logger/-/color-logger-0.0.6.tgz#e56245ef29822657110c7cb75a9cd786cb69ed1b" - integrity sha1-5WJF7ymCJlcRDHy3WpzXhstp7Rs= + integrity sha512-0iBj3eHRYnor8EJi3oQ1kixbr7B2Sbw1InxjsYZxS+q2H+Ii69m3ARYSJeYIqmf/QRtFhWnR1v97wp8N7ABubw== color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" @@ -2253,14 +2540,14 @@ color-name@^1.0.0, color-name@~1.1.4: integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.6.0: - version "1.8.2" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.8.2.tgz#08bd49fa5f3889c27b0c670052ed746dd7a671de" - integrity sha512-w5ZkKRdLsc5NOYsmnpS2DpyRW71npwZGwbRpLrJTuqjfTs2Bhrba7UiV59IX9siBlCPl2pne5NtiwnVWUzvYFA== + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" -color-support@^1.1.2: +color-support@^1.1.2, color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== @@ -2274,14 +2561,9 @@ color@^3.1.3: color-string "^1.6.0" colorette@^2.0.16: - version "2.0.16" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== - -colors@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== colorspace@1.1.x: version "1.1.4" @@ -2294,7 +2576,7 @@ colorspace@1.1.x: columnify@~1.5.4: version "1.5.4" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" - integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs= + integrity sha512-rFl+iXVT1nhLQPfGDw+3WcS8rmm7XsLKUmhsGE3ihzzpIikeGrTaZPIRKYWeLsLBypsHzjXIvYEltVUZS84XxQ== dependencies: strip-ansi "^3.0.0" wcwidth "^1.0.0" @@ -2306,7 +2588,12 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^8.3.0, commander@~8.3.0: +commander@^9.3.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + +commander@~8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== @@ -2324,7 +2611,7 @@ common-ancestor-path@^1.0.1: commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== compare-func@^2.0.0: version "2.0.0" @@ -2334,15 +2621,27 @@ compare-func@^2.0.0: array-ify "^1.0.0" dot-prop "^5.1.0" +compressible@^2.0.12: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +content-type@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== conventional-changelog-angular@^5.0.0, conventional-changelog-angular@^5.0.11: version "5.0.13" @@ -2353,13 +2652,13 @@ conventional-changelog-angular@^5.0.0, conventional-changelog-angular@^5.0.11: q "^1.5.1" conventional-changelog-writer@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz#c4042f3f1542f2f41d7d2e0d6cad23aba8df8eec" - integrity sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g== + version "5.0.1" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz#e0757072f045fe03d91da6343c843029e702f359" + integrity sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ== dependencies: conventional-commits-filter "^2.0.7" dateformat "^3.0.0" - handlebars "^4.7.6" + handlebars "^4.7.7" json-stringify-safe "^5.0.1" lodash "^4.17.15" meow "^8.0.0" @@ -2376,9 +2675,9 @@ conventional-commits-filter@^2.0.0, conventional-commits-filter@^2.0.7: modify-values "^1.0.0" conventional-commits-parser@^3.2.2, conventional-commits-parser@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz#fc43704698239451e3ef35fd1d8ed644f46bd86e" - integrity sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw== + version "3.2.4" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz#a7d3b77758a202a9b2293d2112a8d8052c740972" + integrity sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q== dependencies: JSONStream "^1.0.4" is-text-path "^1.0.1" @@ -2388,11 +2687,14 @@ conventional-commits-parser@^3.2.2, conventional-commits-parser@^3.2.3: through2 "^4.0.0" convert-source-map@^1.5.0, convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +copy-to@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/copy-to/-/copy-to-2.0.1.tgz#2680fbb8068a48d08656b6098092bdafc906f4a5" + integrity sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w== copyfiles@^2.4.1: version "2.4.1" @@ -2415,7 +2717,7 @@ core-js@^2.4.0: core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== core-util-is@~1.0.0: version "1.0.3" @@ -2423,9 +2725,9 @@ core-util-is@~1.0.0: integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== cosmiconfig@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" import-fresh "^3.2.1" @@ -2459,21 +2761,21 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -css-select@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067" - integrity sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA== +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== dependencies: boolbase "^1.0.0" - css-what "^5.0.0" - domhandler "^4.2.0" - domutils "^2.6.0" - nth-check "^2.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" css-select@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= + integrity sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA== dependencies: boolbase "~1.0.0" css-what "2.1" @@ -2485,10 +2787,10 @@ css-what@2.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== -css-what@^5.0.0, css-what@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== +css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0": version "0.3.8" @@ -2498,7 +2800,7 @@ cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0": "cssstyle@>= 0.2.29 < 0.3.0": version "0.2.37" resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54" - integrity sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ= + integrity sha512-FUpKc+1FNBsHUr9IsfSGCovr8VuGOiiuzlgCyppKBjJi2jYTOFLN3oiiNRMIvYqbFzF38mqKj4BgcevzU5/kIA== dependencies: cssom "0.3.x" @@ -2510,14 +2812,19 @@ dargs@^7.0.0: dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== dependencies: assert-plus "^1.0.0" +data-uri-to-buffer@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" + integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== + date-utils@*: version "1.2.21" resolved "https://registry.yarnpkg.com/date-utils/-/date-utils-1.2.21.tgz#61fb16cdc1274b3c9acaaffe9fc69df8720a2b64" - integrity sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q= + integrity sha512-wJMBjqlwXR0Iv0wUo/lFbhSQ7MmG1hl36iuxuE91kW+5b5sWbase73manEqNH9sOLFAMG83B4ffNKq9/Iq0FVA== dateformat@^3.0.0: version "3.0.3" @@ -2531,21 +2838,21 @@ debug@3.2.6: dependencies: ms "^2.1.1" -debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^2.6.8: +debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@^3.1.0, debug@^3.2.6: +debug@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -2555,12 +2862,12 @@ debug@^3.1.0, debug@^3.2.6: debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" - integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= + integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw== decamelize-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= + version "1.1.1" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" + integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== dependencies: decamelize "^1.1.0" map-obj "^1.0.0" @@ -2568,12 +2875,12 @@ decamelize-keys@^1.1.0: decamelize@^1.1.0, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== +deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== dependencies: type-detect "^4.0.0" @@ -2588,30 +2895,48 @@ deep-is@^0.1.3, deep-is@~0.1.3: integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== default-require-extensions@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" - integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.1.tgz#bfae00feeaeada68c2ae256c62540f60b80625bd" + integrity sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw== dependencies: strip-bom "^4.0.0" +default-user-agent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-user-agent/-/default-user-agent-1.0.0.tgz#16c46efdcaba3edc45f24f2bd4868b01b7c2adc6" + integrity sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw== + dependencies: + os-name "~1.0.3" + defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== dependencies: clone "^1.0.2" -define-properties@^1.1.2, define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== +define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== dependencies: - object-keys "^1.0.12" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +degenerator@^3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-3.0.4.tgz#07ccf95bc11044a37a6efc2f66029fb636e31f24" + integrity sha512-Z66uPeBfHZAHVmue3HPfyKu2Q0rC2cRxbTOsvmU/po5fvvcx27W4mIu9n0PUlQih4oUYvcG1BsbtVv8x7KDOSw== + dependencies: + ast-types "^0.13.2" + escodegen "^1.8.1" + esprima "^4.0.0" + vm2 "^3.9.17" del@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" - integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== + version "6.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" + integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg== dependencies: globby "^11.0.1" graceful-fs "^4.2.4" @@ -2630,29 +2955,19 @@ delay@^5.0.0: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -denque@^1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" - integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== denque@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/denque/-/denque-2.0.1.tgz#bcef4c1b80dc32efe97515744f21a4229ab8934a" - integrity sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ== - -depd@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + version "2.1.0" + resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" + integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== -depd@^2.0.0: +depd@2.0.0, depd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -2662,10 +2977,15 @@ deprecation@^2.0.0, deprecation@^2.3.1: resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== +destroy@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + detect-indent@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-3.0.1.tgz#9dc5e5ddbceef8325764b9451b02bc6d54084f75" - integrity sha1-ncXl3bzu+DJXZLlFGwK8bVQIT3U= + integrity sha512-xo3WP66SNbr1Eim85s/qyH0ZL8PQUwp86HWm0S1l8WnJ/zjT6T3w1nwNA0yOZeuvOemupEYvpvF6BIdYRuERJQ== dependencies: get-stdin "^4.0.1" minimist "^1.1.0" @@ -2674,14 +2994,19 @@ detect-indent@^3.0.1: detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= + integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== dependencies: repeating "^2.0.0" +detect-libc@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" + integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== + dezalgo@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" - integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= + version "1.0.4" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" + integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== dependencies: asap "^2.0.0" wrappy "1" @@ -2697,9 +3022,14 @@ diff@^4.0.1: integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== diff@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + +digest-header@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/digest-header/-/digest-header-1.1.0.tgz#e16ab6cf4545bc4eea878c8c35acd1b89664d800" + integrity sha512-glXVh42vz40yZb9Cq2oMOt70FIoWiv+vxNvdKdU8CwjLad25qHM3trLxhl9bVjdr6WaslIXhWpn0NO8T/67Qjg== dir-glob@^3.0.0, dir-glob@^3.0.1: version "3.0.1" @@ -2723,14 +3053,14 @@ dom-serializer@0: domelementtype "^2.0.1" entities "^2.0.0" -dom-serializer@^1.0.1, dom-serializer@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" dom-serializer@~0.1.0: version "0.1.1" @@ -2745,15 +3075,15 @@ domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== +domelementtype@^2.0.1, domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== domhandler@2.3: version "2.3.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" - integrity sha1-LeWaCCLVAn+r/28DLCsloqir5zg= + integrity sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ== dependencies: domelementtype "1" @@ -2764,17 +3094,17 @@ domhandler@^2.3.0: dependencies: domelementtype "1" -domhandler@^4.0.0, domhandler@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f" - integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w== +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== dependencies: - domelementtype "^2.2.0" + domelementtype "^2.3.0" domutils@1.5, domutils@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= + integrity sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw== dependencies: dom-serializer "0" domelementtype "1" @@ -2787,14 +3117,14 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" -domutils@^2.5.2, domutils@^2.6.0, domutils@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" dot-prop@^5.1.0: version "5.3.0" @@ -2803,15 +3133,15 @@ dot-prop@^5.1.0: dependencies: is-obj "^2.0.0" -dottie@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.2.tgz#cc91c0726ce3a054ebf11c55fbc92a7f266dd154" - integrity sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg== +dottie@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.6.tgz#34564ebfc6ec5e5772272d466424ad5b696484d4" + integrity sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA== duplexer2@~0.1.0, duplexer2@~0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= + integrity sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA== dependencies: readable-stream "^2.0.2" @@ -2825,25 +3155,45 @@ duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +duplexify@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" + integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== dependencies: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecdsa-sig-formatter@1.0.11: +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== dependencies: safe-buffer "^5.0.1" -electron-to-chromium@^1.4.71: - version "1.4.72" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.72.tgz#19b871f1da8be8199b2330d694fc84fcdb72ecd9" - integrity sha512-9LkRQwjW6/wnSfevR21a3k8sOJ+XWSH7kkzs9/EUenKmuDkndP3W9y1yCZpOxufwGbX3JV8glZZSDb4o95zwXQ== +ee-first@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.431: + version "1.4.432" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.432.tgz#154a69d5ead974347f534aea4d28b03c7149fd7b" + integrity sha512-yz3U/khQgAFT2HURJA3/F4fKIyO2r5eK09BQzBZFd6BvBSSaRuzKc2ZNBHtJcO75/EKiRYbVYJZ2RB0P4BuD2g== emitter-listener@^1.0.1: version "1.1.2" @@ -2879,24 +3229,22 @@ encoding@^0.1.12: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.0.0, end-of-stream@^1.1.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -enquirer@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" +ent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== entities@1.0: version "1.0.0" resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" - integrity sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY= + integrity sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ== entities@^1.1.1, entities@~1.1.1: version "1.1.2" @@ -2908,15 +3256,20 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.2.0, entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + entities@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== env-ci@^5.0.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/env-ci/-/env-ci-5.4.1.tgz#814387ddd6857b37472ef612361f34d720c29a18" - integrity sha512-xyuCtyFZLpnW5aH0JstETKTSMwHHQX4m42juzEZzvbUCJX7RiPVlhASKM0f/cJ4vvI/+txMkZ7F5To6dCdPYhg== + version "5.5.0" + resolved "https://registry.yarnpkg.com/env-ci/-/env-ci-5.5.0.tgz#43364e3554d261a586dec707bc32be81112b545f" + integrity sha512-o0JdWIbOLP+WJKIUt36hz1ImQQFuN92nhsfTkHHap+J8CiI8WgGpH/a9jEGHh4/TU5BUUGjlnKXNoDb57+ne+A== dependencies: execa "^5.0.0" fromentries "^1.3.2" @@ -2939,31 +3292,59 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" - integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== +es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== dependencies: + array-buffer-byte-length "^1.0.0" + available-typed-arrays "^1.0.5" call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.0" get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" is-regex "^1.1.4" - is-shared-array-buffer "^1.0.1" + is-shared-array-buffer "^1.0.2" is-string "^1.0.7" - is-weakref "^1.0.1" - object-inspect "^1.11.0" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" es-to-primitive@^1.2.1: version "1.2.1" @@ -2979,18 +3360,6 @@ es6-error@^4.0.1: resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -es6-promise@^4.0.3: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= - dependencies: - es6-promise "^4.0.3" - esbuild-android-arm64@0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.3.tgz#f0fc0a892dd6f2f42baf68f9ac24c9bfcfdaba20" @@ -3104,22 +3473,22 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-html@1.0.3: +escape-html@1.0.3, escape-html@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escodegen@^1.6.1: +escodegen@^1.6.1, escodegen@^1.8.1: version "1.14.3" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== @@ -3134,7 +3503,7 @@ escodegen@^1.6.1: esdoc-accessor-plugin@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esdoc-accessor-plugin/-/esdoc-accessor-plugin-1.0.0.tgz#791ba4872e6c403515ce749b1348d6f0293ad9eb" - integrity sha1-eRukhy5sQDUVznSbE0jW8Ck62es= + integrity sha512-s9mNmdHGOyQOaOUXNHPz38Y8clm6dR8/fa9DPGzuRYmIN+Lv0NVnpPAcHb5XrfC23/Mz3IUwD8h798f5Ai4rbA== esdoc-brand-plugin@^1.0.0: version "1.0.1" @@ -3146,24 +3515,24 @@ esdoc-brand-plugin@^1.0.0: esdoc-coverage-plugin@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/esdoc-coverage-plugin/-/esdoc-coverage-plugin-1.1.0.tgz#3869869cd7f87891f972625787695a299aece45c" - integrity sha1-OGmGnNf4eJH5cmJXh2laKZrs5Fw= + integrity sha512-M+94/Y+eoM08V3teiJIYpJ5HF13jH4cC9LQZrjmA91mlAqCHtNzelHF9ZdWofoOFYFRNpllFsXTFsJgwVa000A== esdoc-ecmascript-proposal-plugin@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esdoc-ecmascript-proposal-plugin/-/esdoc-ecmascript-proposal-plugin-1.0.0.tgz#390dc5656ba8a2830e39dba3570d79138df2ffd9" - integrity sha1-OQ3FZWuoooMOOdujVw15E43y/9k= + integrity sha512-PuaU/O8d+Sb0J6qQdyhmy74h/2cp/2kqsvPuoCiK+50Rw54nlGqXxvWNaaNikS5qntE0FfssnwZtUPa6q4RiXg== esdoc-external-ecmascript-plugin@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esdoc-external-ecmascript-plugin/-/esdoc-external-ecmascript-plugin-1.0.0.tgz#78f565d4a0c5185ac63152614dce1fe1a86688db" - integrity sha1-ePVl1KDFGFrGMVJhTc4f4ahmiNs= + integrity sha512-ASj7lhfZpzI01xd4XqB4HN+zNKwnhdaN/OIp/CTnUiLIErMOeUqzV9z/dcnUUeDY3NSwPCH1pUNATVwznspmHw== dependencies: fs-extra "1.0.0" esdoc-inject-style-plugin@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esdoc-inject-style-plugin/-/esdoc-inject-style-plugin-1.0.0.tgz#a13597368bb9fb89c365e066495caf97a4decbb1" - integrity sha1-oTWXNou5+4nDZeBmSVyvl6Tey7E= + integrity sha512-LqSGr3YKe+vY2u6TCp9K+EEt97S78KjdJUz5PXyitHkp4nGXRSZq2ftEQJioF/WtTeGYWeQLzNAM9LihIlisqg== dependencies: cheerio "0.22.0" fs-extra "1.0.0" @@ -3171,12 +3540,12 @@ esdoc-inject-style-plugin@^1.0.0: esdoc-integrate-manual-plugin@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esdoc-integrate-manual-plugin/-/esdoc-integrate-manual-plugin-1.0.0.tgz#1854a6aa1c081035d7c8c51e3bdd4fb65aa4711c" - integrity sha1-GFSmqhwIEDXXyMUeO91PtlqkcRw= + integrity sha512-+XcW8xRtuFVFadoVLIOj6kzX4uqtAEB5UoR7AA5g46StxLghZZ6RLrRQSERUTIc3VX9v47lOMKEaQvQfanv3+A== esdoc-integrate-test-plugin@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esdoc-integrate-test-plugin/-/esdoc-integrate-test-plugin-1.0.0.tgz#e2d0d00090f7f0c35e5d2f2c033327a79e53e409" - integrity sha1-4tDQAJD38MNeXS8sAzMnp55T5Ak= + integrity sha512-WRbkbnbWnzF4RdmcoJLYZvhod7jLVUYWU2ZAojYjK+GiqSgy2yjGi7PxckeGF0LtpCuqqKat3PRdUNEMo6Nf3A== esdoc-lint-plugin@^1.0.0: version "1.0.2" @@ -3199,7 +3568,7 @@ esdoc-publish-html-plugin@^1.0.0: esdoc-standard-plugin@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esdoc-standard-plugin/-/esdoc-standard-plugin-1.0.0.tgz#661201cac7ef868924902446fdac1527253c5d4d" - integrity sha1-ZhIBysfvhokkkCRG/awVJyU8XU0= + integrity sha512-IDEG9NV/MF5Bi2TdKPqQ3GHfDkgqYhk2iyvBNX+XcNKYmXm9zxtXVS459WAmiTZuYpDLtDGbulQdJ1t4ud57mw== dependencies: esdoc-accessor-plugin "^1.0.0" esdoc-brand-plugin "^1.0.0" @@ -3221,12 +3590,12 @@ esdoc-type-inference-plugin@^1.0.0: esdoc-undocumented-identifier-plugin@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esdoc-undocumented-identifier-plugin/-/esdoc-undocumented-identifier-plugin-1.0.0.tgz#82e05d371c32d12871140f1d5c81ec99fd9cc2c8" - integrity sha1-guBdNxwy0ShxFA8dXIHsmf2cwsg= + integrity sha512-T0hQc0ec1+pUJPDBoJ2SxEv7uX9VD7Q9+7UAGnDZ5R2l2JYa3WY7cawyqfbMHVtLgvqH0eMBpxdfRsQvAWzj4Q== esdoc-unexported-identifier-plugin@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esdoc-unexported-identifier-plugin/-/esdoc-unexported-identifier-plugin-1.0.0.tgz#1f9874c6a7c2bebf9ad397c3ceb75c9c69dabab1" - integrity sha1-H5h0xqfCvr+a05fDzrdcnGnaurE= + integrity sha512-PRdMLWHWdy9PwxzYDG2clhta9H7yHDpGCBIHxSw9R7TFK6ZYuPK1fUbURIzIxcdQhzt1PX9Cn6Cak2824K0+Ng== esdoc@^1.1.0: version "1.1.0" @@ -3246,16 +3615,15 @@ esdoc@^1.1.0: taffydb "2.7.3" eslint-plugin-jsdoc@^37.4.0: - version "37.4.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-37.4.0.tgz#6e6eade5494150a392365f63bbd2fb88caeb8d0c" - integrity sha512-XWKMMHFq7eUdC8XMzuQSskevJvlHTDSAJm/2qtEZ7+qhZTZ0YjeqWaUn7KGdrmxLNqtWwtJ67LdIPgrYUZ5EoA== + version "37.9.7" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-37.9.7.tgz#ef46141aa2e5fcbb89adfa658eef8126435e9eac" + integrity sha512-8alON8yYcStY94o0HycU2zkLKQdcS+qhhOUNQpfONHHwvI99afbmfpYuPqf6PbLz5pLZldG3Te5I0RbAiTN42g== dependencies: - "@es-joy/jsdoccomment" "0.13.0" + "@es-joy/jsdoccomment" "~0.20.1" comment-parser "1.3.0" debug "^4.3.3" escape-string-regexp "^4.0.0" esquery "^1.4.0" - jsdoc-type-pratt-parser "^2.0.0" regextras "^0.8.0" semver "^7.3.5" spdx-expression-parse "^3.0.1" @@ -3276,10 +3644,10 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153" - integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg== +eslint-scope@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -3296,73 +3664,74 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz#eee4acea891814cda67a7d8812d9647dd0179af2" - integrity sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA== +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== eslint@^8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.5.0.tgz#ddd2c1afd8f412036f87ae2a063d2aa296d3175f" - integrity sha512-tVGSkgNbOfiHyVte8bCM8OmX+xG9PzVG/B4UCF60zx7j61WIVY/AqJECDgpLD4DbbESD0e174gOg3ZlrX15GDg== - dependencies: - "@eslint/eslintrc" "^1.0.5" - "@humanwhocodes/config-array" "^0.9.2" + version "8.42.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.42.0.tgz#7bebdc3a55f9ed7167251fe7259f75219cade291" + integrity sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.3" + "@eslint/js" "8.42.0" + "@humanwhocodes/config-array" "^0.11.10" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" doctrine "^3.0.0" - enquirer "^2.3.5" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.0" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.1.0" - espree "^9.2.0" - esquery "^1.4.0" + eslint-scope "^7.2.0" + eslint-visitor-keys "^3.4.1" + espree "^9.5.2" + esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^6.0.1" - globals "^13.6.0" - ignore "^4.0.6" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" + is-path-inside "^3.0.3" js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" - minimatch "^3.0.4" + minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.2.0" - semver "^7.2.1" strip-ansi "^6.0.1" strip-json-comments "^3.1.0" text-table "^0.2.0" - v8-compile-cache "^2.0.3" -espree@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.2.0.tgz#c50814e01611c2d0f8bd4daa83c369eabba80dbc" - integrity sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg== +espree@^9.5.2: + version "9.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b" + integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== dependencies: - acorn "^8.6.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^3.1.0" + acorn "^8.8.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== +esquery@^1.4.0, esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" @@ -3388,10 +3757,15 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + events@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= + integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== events@^3.0.0: version "3.3.0" @@ -3416,7 +3790,7 @@ execa@^5.0.0, execa@^5.1.1: expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== dependencies: homedir-polyfill "^1.0.1" @@ -3425,6 +3799,13 @@ expect-type@^0.12.0: resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-0.12.0.tgz#133534b5e2561158c371e74af63fd8f18a9f3d42" integrity sha512-IHwziEOjpjXqxQhtOAD5zMiQpGztaEKM4Q8wnwoRN9NIFlnyNHNjRxKWv+18UqRfsqi6vVnZIYFU16ePf+HaqA== +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + extend@^3.0.0, extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -3433,7 +3814,7 @@ extend@^3.0.0, extend@^3.0.2, extend@~3.0.2: extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== extsprintf@^1.2.0: version "1.4.1" @@ -3445,10 +3826,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1, fast-glob@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== +fast-glob@^3.2.7, fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -3464,29 +3845,41 @@ fast-json-stable-stringify@^2.0.0: fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-text-encoding@^1.0.0: + version "1.0.6" + resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz#0aa25f7f638222e3396d72bf936afcf1d42d6867" + integrity sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w== + +fast-xml-parser@^4.1.3: + version "4.2.4" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.4.tgz#6e846ede1e56ad9e5ef07d8720809edf0ed07e9b" + integrity sha512-fbfMDvgBNIdDJLdLOwacjFAPYt67tr31H9ZhWSm45CDAxvd0I6WTlSOUo7K2P/K5sA5JgMKG64PI3DMcaFdWpQ== + dependencies: + strnum "^1.0.5" fastest-levenshtein@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" - integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== dependencies: reusify "^1.0.4" fecha@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.1.tgz#0a83ad8f86ef62a091e22bb5a039cd03d23eecce" - integrity sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q== + version "4.2.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" + integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== dependencies: escape-string-regexp "^1.0.5" @@ -3509,6 +3902,11 @@ file-uri-to-path@1.0.0: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== +file-uri-to-path@2: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz#7b415aeba227d575851e0a5b0c640d7656403fba" + integrity sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg== + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -3535,7 +3933,7 @@ find-up@3.0.0, find-up@^3.0.0: find-up@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: locate-path "^2.0.0" @@ -3578,9 +3976,9 @@ flat@^4.1.0: is-buffer "~2.0.3" flatted@^3.1.0: - version "3.2.5" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" - integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== flush-write-stream@^1.0.2: version "1.1.1" @@ -3595,10 +3993,17 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.14.0: - version "1.14.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== +follow-redirects@^1.14.0, follow-redirects@^1.14.8, follow-redirects@^1.14.9: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" foreground-child@^2.0.0: version "2.0.0" @@ -3611,7 +4016,7 @@ foreground-child@^2.0.0: forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== form-data@^2.3.2: version "2.5.1" @@ -3649,10 +4054,19 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +formstream@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/formstream/-/formstream-1.2.0.tgz#6948dfa0d1c64bffe93029abf30326fe7504dc41" + integrity sha512-ef4F+FQLnQLly1/AZ5OGNgGzzlOmp+T7+L/TaXASJ1GrETrpZb78/Mz7z+1Ra5FX3nLZE0WIOInGOoa81LxWew== + dependencies: + destroy "^1.0.4" + mime "^2.5.2" + pause-stream "~0.0.11" + from2@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g== dependencies: inherits "^2.0.1" readable-stream "^2.0.0" @@ -3670,7 +4084,7 @@ fs-constants@^1.0.0: fs-extra@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" - integrity sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA= + integrity sha512-VerQV6vEKuhDWD2HGOybV6v5I73syoc/cXAbKlgTC7M/oFVEtklWlp9QH2Ijw3IaWDOQcMkldSPa7zXy79Z/UQ== dependencies: graceful-fs "^4.1.2" jsonfile "^2.1.0" @@ -3686,9 +4100,18 @@ fs-extra@5.0.0: universalify "^0.1.0" fs-extra@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.1.tgz#27de43b4320e833f6867cc044bfce29fdf0ef3b8" - integrity sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag== + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^11.0.0: + version "11.1.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" + integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -3704,9 +4127,9 @@ fs-extra@^8.1.0: universalify "^0.1.0" fs-jetpack@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/fs-jetpack/-/fs-jetpack-4.3.0.tgz#8202abd21c9160faadf3c258b4cf918a74f680de" - integrity sha512-Zx4OJ8HyKvZL9sgxegMGRCgAJSQET5Cqpj/SESwnzqHruHvhkilJBGLoZf6EiYr3UWJDqcPoWDX7aAfaj7D9Qw== + version "4.3.1" + resolved "https://registry.yarnpkg.com/fs-jetpack/-/fs-jetpack-4.3.1.tgz#cdfd4b64e6bfdec7c7dc55c76b39efaa7853bb20" + integrity sha512-dbeOK84F6BiQzk2yqqCVwCPWTxAvVGJ3fMQc6E2wuEohS28mR6yHngbrKuVCK1KHRx/ccByDylqu4H5PCP2urQ== dependencies: minimatch "^3.0.2" rimraf "^2.6.3" @@ -3721,7 +4144,7 @@ fs-minipass@^2.0.0, fs-minipass@^2.1.0: fs-mkdirp-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" - integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= + integrity sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ== dependencies: graceful-fs "^4.1.11" through2 "^2.0.3" @@ -3729,7 +4152,7 @@ fs-mkdirp-stream@^1.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.1.1: version "2.1.3" @@ -3746,20 +4169,38 @@ fstream@^1.0.12: mkdirp ">=0.5 0" rimraf "2" +ftp@^0.3.10: + version "0.3.10" + resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d" + integrity sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ== + dependencies: + readable-stream "1.1.x" + xregexp "2.0.0" + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + +functions-have-names@^1.2.2, functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== gauge@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.1.tgz#4bea07bcde3782f06dced8950e51307aa0f4a346" - integrity sha512-6STz6KdQgxO4S/ko+AbjlFGGdGcknluoqU+79GOFCDqqyYj5OanQf9AjxwN0jCidtT+ziPMmPSt9E4hfQ0CwIQ== + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== dependencies: aproba "^1.0.3 || ^2.0.0" color-support "^1.1.2" @@ -3767,14 +4208,28 @@ gauge@^3.0.0: has-unicode "^2.0.1" object-assign "^4.1.1" signal-exit "^3.0.0" - string-width "^1.0.1 || ^2.0.0" - strip-ansi "^3.0.1 || ^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" wide-align "^1.1.2" +gauge@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" + integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^3.0.7" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -3785,6 +4240,24 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gaxios@^5.0.0, gaxios@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-5.1.0.tgz#133b77b45532be71eec72012b7e97c2320b6140a" + integrity sha512-aezGIjb+/VfsJtIcHGcBSerNEDdfdHeMros+RbYbGpmonKWQCOVOes0LVZhn1lDtIgq55qq0HaxymIoae3Fl/A== + dependencies: + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.6.7" + +gcp-metadata@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-5.2.0.tgz#b4772e9c5976241f5d3e69c4f446c906d25506ec" + integrity sha512-aFhhvvNycky2QyhG+dcfEdHBF0FRbYcf39s6WNHUDysKSrbJ5vuFbjydxBcmewtXeV248GP8dWT3ByPNxsyHCw== + dependencies: + gaxios "^5.0.0" + json-bigint "^1.0.0" + generate-function@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" @@ -3793,20 +4266,15 @@ generate-function@^2.3.1: is-property "^1.0.2" generic-pool@^3.8.2: - version "3.8.2" - resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.8.2.tgz#aab4f280adb522fdfbdc5e5b64d718d3683f04e9" - integrity sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg== + version "3.9.0" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4" + integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -3815,16 +4283,17 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: get-func-name@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== dependencies: function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" + has-proto "^1.0.1" + has-symbols "^1.0.3" get-package-type@^0.1.0: version "0.1.0" @@ -3834,7 +4303,7 @@ get-package-type@^0.1.0: get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= + integrity sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw== get-stdin@~8.0.0: version "8.0.0" @@ -3854,17 +4323,29 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +get-uri@3: + version "3.0.2" + resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c" + integrity sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg== + dependencies: + "@tootallnate/once" "1" + data-uri-to-buffer "3" + debug "4" + file-uri-to-path "2" + fs-extra "^8.1.0" + ftp "^0.3.10" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== dependencies: assert-plus "^1.0.0" git-log-parser@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/git-log-parser/-/git-log-parser-1.2.0.tgz#2e6a4c1b13fc00028207ba795a7ac31667b9fd4a" - integrity sha1-LmpMGxP8AAKCB7p5WnrDFme5/Uo= + integrity sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA== dependencies: argv-formatter "~1.0.0" spawn-error-forwarder "~1.0.0" @@ -3874,9 +4355,9 @@ git-log-parser@^1.2.0: traverse "~0.6.6" git-raw-commits@^2.0.0: - version "2.0.10" - resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.10.tgz#e2255ed9563b1c9c3ea6bd05806410290297bbc1" - integrity sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ== + version "2.0.11" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723" + integrity sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A== dependencies: dargs "^7.0.0" lodash "^4.17.15" @@ -3887,7 +4368,7 @@ git-raw-commits@^2.0.0: glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + integrity sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA== dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" @@ -3899,7 +4380,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.1: +glob-parent@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== @@ -3909,7 +4390,7 @@ glob-parent@^6.0.1: glob-stream@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" - integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= + integrity sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw== dependencies: extend "^3.0.0" glob "^7.1.1" @@ -3935,21 +4416,21 @@ glob@7.1.3: path-is-absolute "^1.0.0" glob@^7.0.5, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0, glob@~7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" global-dirs@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= + integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg== dependencies: ini "^1.3.4" @@ -3958,10 +4439,10 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.6.0, globals@^13.9.0: - version "13.12.1" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb" - integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw== +globals@^13.19.0: + version "13.20.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== dependencies: type-fest "^0.20.2" @@ -3970,34 +4451,84 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== -globby@^11.0.0, globby@^11.0.1, globby@^11.0.4: - version "11.0.4" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" - integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^11.0.0, globby@^11.0.1, globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== +google-auth-library@^8.0.1: + version "8.8.0" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-8.8.0.tgz#2e17494431cef56b571420d483a4debff6c481cd" + integrity sha512-0iJn7IDqObDG5Tu9Tn2WemmJ31ksEa96IyK0J0OZCpTh6CrC6FrattwKX87h3qKVuprCJpdOGKc1Xi8V0kMh8Q== + dependencies: + arrify "^2.0.0" + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + fast-text-encoding "^1.0.0" + gaxios "^5.0.0" + gcp-metadata "^5.2.0" + gtoken "^6.1.0" + jws "^4.0.0" + lru-cache "^6.0.0" + +google-p12-pem@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-4.0.1.tgz#82841798253c65b7dc2a4e5fe9df141db670172a" + integrity sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ== + dependencies: + node-forge "^1.3.1" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.8: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== -graceful-fs@^4.2.3, graceful-fs@^4.2.8: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -handlebars@^4.7.6: +gtoken@^6.1.0: + version "6.1.2" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-6.1.2.tgz#aeb7bdb019ff4c3ba3ac100bbe7b6e74dce0e8bc" + integrity sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ== + dependencies: + gaxios "^5.0.1" + google-p12-pem "^4.0.0" + jws "^4.0.0" + +handlebars@^4.7.7: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== @@ -4012,7 +4543,7 @@ handlebars@^4.7.6: har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== har-validator@~5.1.3: version "5.1.5" @@ -4030,29 +4561,41 @@ hard-rejection@^2.1.0: has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== dependencies: ansi-regex "^2.0.0" -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.0, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-tostringtag@^1.0.0: version "1.0.0" @@ -4064,7 +4607,7 @@ has-tostringtag@^1.0.0: has-unicode@^2.0.0, has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== has@^1.0.3: version "1.0.3" @@ -4103,20 +4646,13 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== -hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: +hosted-git-info@^4.0.0, hosted-git-info@^4.0.1, hosted-git-info@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== dependencies: lru-cache "^6.0.0" -hosted-git-info@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961" - integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== - dependencies: - lru-cache "^6.0.0" - html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -4134,20 +4670,20 @@ htmlparser2@^3.9.1: inherits "^2.0.1" readable-stream "^3.1.1" -htmlparser2@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" - integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== +htmlparser2@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" + integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== dependencies: - domelementtype "^2.0.1" - domhandler "^4.0.0" - domutils "^2.5.2" - entities "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + entities "^4.4.0" htmlparser2@~3.8.1: version "3.8.3" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" - integrity sha1-mWwosZFRaovoZQGn15dX5ccMEGg= + integrity sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q== dependencies: domelementtype "1" domhandler "2.3" @@ -4156,11 +4692,22 @@ htmlparser2@~3.8.1: readable-stream "1.1" http-cache-semantics@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" -http-proxy-agent@^4.0.1: +http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== @@ -4178,38 +4725,37 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" -http-signature@^1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9" - integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw== +http-proxy-agent@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz#e9096c5afd071a3fce56e6252bb321583c124673" + integrity sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ== dependencies: - assert-plus "^1.0.0" - jsprim "^2.0.2" - sshpk "^1.14.1" + agent-base "^7.1.0" + debug "^4.3.4" http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== dependencies: assert-plus "^1.0.0" jsprim "^1.2.2" sshpk "^1.7.0" -https-proxy-agent@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz#b8c286433e87602311b01c8ea34413d856a4af81" - integrity sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg== +https-proxy-agent@5, https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: - agent-base "^4.3.0" - debug "^3.1.0" + agent-base "6" + debug "4" -https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== +https-proxy-agent@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.0.tgz#75cb70d04811685667183b31ab158d006750418a" + integrity sha512-0euwPCRyAPSgGdzD1IVN9nJYHtBhJwb6XPfbpQcYbPCwrBidX6GzxmchnaF4sfF/jPb74Ojx5g4yTg3sixlyPw== dependencies: - agent-base "6" + agent-base "^7.0.2" debug "4" human-signals@^2.1.0: @@ -4217,10 +4763,10 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -humanize-ms@^1.2.1: +humanize-ms@^1.2.0, humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" - integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== dependencies: ms "^2.0.0" @@ -4230,11 +4776,11 @@ husky@^7.0.4: integrity sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ== ibm_db@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/ibm_db/-/ibm_db-2.8.1.tgz#1b018d1fc9c6b5bd205b603e43a09584e1dbecc0" - integrity sha512-w4q5UN5FNRf4PW2yDG3uQVnA81vy2GS4vkGwigKgBuUMRa+pNgbAtTkhv3w/9Vz12X6YiYK9hFcwlVomKdj0qw== + version "2.8.2" + resolved "https://registry.yarnpkg.com/ibm_db/-/ibm_db-2.8.2.tgz#bc5a22c2859a95de577088f4f2bf72fb6da6107b" + integrity sha512-cvvvz/VGeniQRHpSpiJmw2wJxkLG5ewcS1DLOW9rvHYBMBvyCM54O7ZhCSlsX1+XV5QKyKdvhjQxld+uoiZJlA== dependencies: - axios "^0.21.1" + axios "^0.26.1" big-integer "^1.6.51" bindings "^1.5.0" fs-extra "^8.1.0" @@ -4248,11 +4794,18 @@ ibm_db@^2.8.1: ice-cap@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/ice-cap/-/ice-cap-0.0.4.tgz#8a6d31ab4cac8d4b56de4fa946df3352561b6e18" - integrity sha1-im0xq0ysjUtW3k+pRt8zUlYbbhg= + integrity sha512-39ZblYEKlqj7LHgLkUcVk7zcJp772lOVQAUhN6QyY88w8/4bn5SgDeU2020yzHosf+uKPuCFK1UQ36gyBNiraw== dependencies: cheerio "0.20.0" color-logger "0.0.3" +iconv-lite@0.4.24, iconv-lite@^0.4.15: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + iconv-lite@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.2.tgz#af6d628dccfb463b7364d97f715e4b74b8c8c2b8" @@ -4284,12 +4837,12 @@ ignore-walk@^3.0.3: dependencies: minimatch "^3.0.4" -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== -ignore@^5.1.4, ignore@^5.1.8, ignore@~5.1.9: +ignore@~5.1.9: version "5.1.9" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb" integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ== @@ -4310,7 +4863,7 @@ import-from@^4.0.0: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indent-string@^4.0.0: version "4.0.0" @@ -4322,20 +4875,20 @@ infer-owner@^1.0.4: resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== -inflection@^1.13.2: - version "1.13.2" - resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.2.tgz#15e8c797c6c3dadf31aa658f8df8a4ea024798b0" - integrity sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw== +inflection@^1.13.4: + version "1.13.4" + resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.4.tgz#65aa696c4e2da6225b148d7a154c449366633a32" + integrity sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -4345,11 +4898,16 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -ini@^2.0.0, ini@~2.0.0: +ini@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== +ini@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ini/-/ini-3.0.1.tgz#c76ec81007875bc44d544ff7a11a55d12294102d" + integrity sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ== + init-package-json@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-2.0.5.tgz#78b85f3c36014db42d8f32117252504f68022646" @@ -4363,12 +4921,12 @@ init-package-json@^2.0.5: validate-npm-package-license "^3.0.4" validate-npm-package-name "^3.0.0" -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== dependencies: - get-intrinsic "^1.1.0" + get-intrinsic "^1.2.0" has "^1.0.3" side-channel "^1.0.4" @@ -4393,9 +4951,14 @@ ip-regex@^4.1.0: integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + version "1.1.8" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" + integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== + +ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" + integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== is-absolute@^1.0.0: version "1.0.0" @@ -4405,10 +4968,27 @@ is-absolute@^1.0.0: is-relative "^1.0.0" is-windows "^1.0.1" +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-arrayish@^0.3.1: version "0.3.2" @@ -4447,10 +5027,10 @@ is-buffer@~2.0.3: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-cidr@^4.0.2: version "4.0.2" @@ -4459,10 +5039,10 @@ is-cidr@^4.0.2: dependencies: cidr-regex "^3.1.1" -is-core-module@^2.5.0, is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== +is-core-module@^2.11.0, is-core-module@^2.5.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== dependencies: has "^1.0.3" @@ -4478,10 +5058,15 @@ is-docker@^2.0.0: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== +is-extendable@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-finite@^1.0.0: version "1.1.0" @@ -4491,14 +5076,14 @@ is-finite@^1.0.0: is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -4510,10 +5095,17 @@ is-fullwidth-code-point@^4.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + integrity sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw== dependencies: is-extglob "^2.1.0" @@ -4527,22 +5119,22 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: is-lambda@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" - integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= + integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== is-negated-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" - integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= + integrity sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug== -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== dependencies: has-tostringtag "^1.0.0" @@ -4561,7 +5153,7 @@ is-path-cwd@^2.2.0: resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== -is-path-inside@^3.0.2: +is-path-inside@^3.0.2, is-path-inside@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== @@ -4569,7 +5161,7 @@ is-path-inside@^3.0.2: is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== is-plain-object@^5.0.0: version "5.0.0" @@ -4579,7 +5171,7 @@ is-plain-object@^5.0.0: is-property@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= + integrity sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g== is-regex@^1.1.4: version "1.1.4" @@ -4596,10 +5188,12 @@ is-relative@^1.0.0: dependencies: is-unc-path "^1.0.0" -is-shared-array-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" - integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" is-stream@^2.0.0: version "2.0.1" @@ -4623,14 +5217,25 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: is-text-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" - integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4= + integrity sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w== dependencies: text-extensions "^1.0.0" +is-typed-array@^1.1.10, is-typed-array@^1.1.3, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== is-unc-path@^1.0.0: version "1.0.0" @@ -4642,19 +5247,19 @@ is-unc-path@^1.0.0: is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== is-valid-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" - integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= + integrity sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA== -is-weakref@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2" - integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ== +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" @@ -4671,22 +5276,27 @@ is-wsl@^2.1.1: isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== issue-parser@^6.0.0: version "6.0.0" @@ -4699,7 +5309,7 @@ issue-parser@^6.0.0: lodash.isstring "^4.0.1" lodash.uniqby "^4.7.0" -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== @@ -4722,17 +5332,16 @@ istanbul-lib-instrument@^4.0.0: semver "^6.3.0" istanbul-lib-processinfo@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz#e1426514662244b2f25df728e8fd1ba35fe53b9c" - integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz#366d454cd0dcb7eb6e0e419378e60072c8626169" + integrity sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg== dependencies: archy "^1.0.0" - cross-spawn "^7.0.0" - istanbul-lib-coverage "^3.0.0-alpha.1" - make-dir "^3.0.0" + cross-spawn "^7.0.3" + istanbul-lib-coverage "^3.2.0" p-map "^3.0.0" rimraf "^3.0.0" - uuid "^3.3.3" + uuid "^8.3.2" istanbul-lib-report@^3.0.0: version "3.0.0" @@ -4753,9 +5362,9 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.0.2: - version "3.1.4" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" - integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -4783,7 +5392,7 @@ js-combinatorics@^0.6.1: js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== js-yaml@3.13.1: version "3.13.1" @@ -4816,17 +5425,17 @@ jsbi@^3.1.1: jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -jsdoc-type-pratt-parser@2.0.0, jsdoc-type-pratt-parser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-2.0.0.tgz#ec739a0868922515fcb179852e990e89b52b9044" - integrity sha512-sUuj2j48wxrEpbFjDp1sAesAxPiLT+z0SWVmMafyIINs6Lj5gIPKh3VrkBZu4E/Dv+wHpOot0m6H8zlHQjwqeQ== +jsdoc-type-pratt-parser@~2.2.3: + version "2.2.5" + resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-2.2.5.tgz#c9f93afac7ee4b5ed4432fe3f09f7d36b05ed0ff" + integrity sha512-2a6eRxSxp1BW040hFvaJxhsCMI9lT8QB8t14t+NY5tC5rckIR0U9cr2tjOeaFirmEOy6MHvmJnY7zTBHq431Lw== jsdom@^7.0.2: version "7.2.2" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-7.2.2.tgz#40b402770c2bda23469096bee91ab675e3b1fc6e" - integrity sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4= + integrity sha512-kYeYuos/pYp0V/V8VAoGnUc0va0UZjTjwCsldBFZNBrOi9Q5kUXrvsw6W5/lQllB7hKXBARC4HRk1Sfk4dPFtA== dependencies: abab "^1.0.0" acorn "^2.4.0" @@ -4847,13 +5456,20 @@ jsdom@^7.0.2: jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= + integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -4869,7 +5485,7 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema@0.4.0, json-schema@^0.4.0: +json-schema@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== @@ -4877,7 +5493,7 @@ json-schema@0.4.0, json-schema@^0.4.0: json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stringify-nice@^1.1.4: version "1.1.4" @@ -4887,14 +5503,12 @@ json-stringify-nice@^1.1.4: json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" +json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonc-parser@~3.0.0: version "3.0.0" @@ -4904,14 +5518,14 @@ jsonc-parser@~3.0.0: jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== optionalDependencies: graceful-fs "^4.1.6" jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== optionalDependencies: graceful-fs "^4.1.6" @@ -4927,23 +5541,17 @@ jsonfile@^6.0.1: jsonparse@^1.2.0, jsonparse@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== -jsonwebtoken@^8.5.1: - version "8.5.1" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" - integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== +jsonwebtoken@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d" + integrity sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw== dependencies: jws "^3.2.2" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" + lodash "^4.17.21" ms "^2.1.1" - semver "^5.6.0" + semver "^7.3.8" jsprim@^1.2.2: version "1.4.2" @@ -4955,16 +5563,6 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" -jsprim@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" - integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - just-diff-apply@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/just-diff-apply/-/just-diff-apply-3.1.2.tgz#710d8cda00c65dc4e692df50dbe9bac5581c2193" @@ -4989,6 +5587,15 @@ jwa@^1.4.1: ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" +jwa@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" + integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + jws@3.x.x, jws@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" @@ -4997,6 +5604,14 @@ jws@3.x.x, jws@^3.2.2: jwa "^1.4.1" safe-buffer "^5.0.1" +jws@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" + integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + dependencies: + jwa "^2.0.0" + safe-buffer "^5.0.1" + kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -5005,7 +5620,7 @@ kind-of@^6.0.3: klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= + integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== optionalDependencies: graceful-fs "^4.1.9" @@ -5022,18 +5637,19 @@ lazystream@^1.0.0: readable-stream "^2.0.5" lcov-result-merger@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lcov-result-merger/-/lcov-result-merger-3.1.0.tgz#ae6d1be663dbf7d586d8004642359d39de72039e" - integrity sha512-vGXaMNGZRr4cYvW+xMVg+rg7qd5DX9SbGXl+0S3k85+gRZVK4K7UvxPWzKb/qiMwe+4bx3EOrW2o4mbdb1WnsA== + version "3.3.0" + resolved "https://registry.yarnpkg.com/lcov-result-merger/-/lcov-result-merger-3.3.0.tgz#66d4b12ced4830855404db82622ac9e450304205" + integrity sha512-Krg9p24jGaIT93RBMA8b5qLHDEiAXTavaTiEdMAZaJS93PsBKIcg/89cw/8rgeSfRuQX+I9x7h73SHFjCZ6cHg== dependencies: through2 "^2.0.3" vinyl "^2.1.0" vinyl-fs "^3.0.2" + yargs "^16.2.0" lead@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" - integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= + integrity sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow== dependencies: flush-write-stream "^1.0.2" @@ -5048,7 +5664,7 @@ levn@^0.4.1: levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" @@ -5163,10 +5779,10 @@ libnpmversion@^1.2.1: semver "^7.3.5" stringify-package "^1.0.1" -lilconfig@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" - integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== +lilconfig@2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25" + integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg== lines-and-columns@^1.1.6: version "1.2.4" @@ -5181,47 +5797,48 @@ linkify-it@^3.0.1: uc.micro "^1.0.1" lint-staged@^12.1.4: - version "12.1.4" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.1.4.tgz#a92ec8509f13018caaafade61d515c2d5873316e" - integrity sha512-RgDz9nsFsE0/5eL9Vat0AvCuk0+j5mEuzBIVfrRH5FRtt5wibYe8zTjZs2nuqLFrLAGQGYnj8+HJxolcj08i/A== + version "12.5.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.5.0.tgz#d6925747480ae0e380d13988522f9dd8ef9126e3" + integrity sha512-BKLUjWDsKquV/JuIcoQW4MSAI3ggwEImF1+sB4zaKvyVx1wBk3FsG7UK9bpnmBTN1pm7EH2BBcMwINJzCRv12g== dependencies: cli-truncate "^3.1.0" colorette "^2.0.16" - commander "^8.3.0" - debug "^4.3.3" + commander "^9.3.0" + debug "^4.3.4" execa "^5.1.1" - lilconfig "2.0.4" - listr2 "^3.13.5" - micromatch "^4.0.4" + lilconfig "2.0.5" + listr2 "^4.0.5" + micromatch "^4.0.5" normalize-path "^3.0.0" - object-inspect "^1.11.1" + object-inspect "^1.12.2" + pidtree "^0.5.0" string-argv "^0.3.1" - supports-color "^9.2.1" + supports-color "^9.2.2" yaml "^1.10.2" listenercount@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937" - integrity sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc= + integrity sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ== -listr2@^3.13.5: - version "3.13.5" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.13.5.tgz#105a813f2eb2329c4aae27373a281d610ee4985f" - integrity sha512-3n8heFQDSk+NcwBn3CgxEibZGaRzx+pC64n3YjpMD1qguV4nWus3Al+Oo3KooqFKTQEJ1v7MmnbnyyNspgx3NA== +listr2@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5" + integrity sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA== dependencies: cli-truncate "^2.1.0" colorette "^2.0.16" log-update "^4.0.0" p-map "^4.0.0" rfdc "^1.3.0" - rxjs "^7.4.0" + rxjs "^7.5.5" through "^2.3.8" wrap-ansi "^7.0.0" load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== dependencies: graceful-fs "^4.1.2" parse-json "^4.0.0" @@ -5231,7 +5848,7 @@ load-json-file@^4.0.0: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -5261,132 +5878,107 @@ locate-path@^6.0.0: lodash.assignin@^4.0.9: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" - integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= + integrity sha512-yX/rx6d/UTVh7sSVWVSIMjfnz95evAgDFdb1ZozC35I9mSFCkmzptOzevxjgbQUsc78NR44LVHWjsoMQXy9FDg== lodash.bind@^4.1.4: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" - integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= + integrity sha512-lxdsn7xxlCymgLYo1gGvVrfHmkjDiyqVv62FAeF2i5ta72BipE1SLxw8hPEPLhD4/247Ijw07UQH7Hq/chT5LA== lodash.capitalize@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9" - integrity sha1-+CbJtOKoUR2E46yinbBeGk87cqk= + integrity sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw== lodash.defaults@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= + integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== lodash.differencewith@~4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.differencewith/-/lodash.differencewith-4.5.0.tgz#bafafbc918b55154e179176a00bb0aefaac854b7" - integrity sha1-uvr7yRi1UVTheRdqALsK76rIVLc= + integrity sha512-/8JFjydAS+4bQuo3CpLMBv7WxGFyk7/etOAsrQUCu0a9QVDemxv0YQ0rFyeZvqlUD314SERfNlgnlqqHmaQ0Cg== lodash.escaperegexp@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" - integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c= + integrity sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw== lodash.filter@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" - integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= + integrity sha512-pXYUy7PR8BCLwX5mgJ/aNtyOvuJTdZAo9EQFUvMIYugqmJxnrYaANvTbgndOzHSCSR0wnlBBfRXJL5SbWxo3FQ== lodash.flatten@^4.2.0, lodash.flatten@~4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= + integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== lodash.flattendeep@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" - integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= + integrity sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ== lodash.foreach@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" - integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= + integrity sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ== lodash.get@^4, lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= - -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= - -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" - integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= + integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g== lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== lodash.isstring@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== lodash.map@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" - integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= + integrity sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q== lodash.merge@^4.4.0, lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= - lodash.pick@^4.2.1: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" - integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= + integrity sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q== lodash.reduce@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" - integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= + integrity sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw== lodash.reject@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" - integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= + integrity sha512-qkTuvgEzYdyhiJBx42YPzPo71R1aEr0z79kAv7Ixg8wPFEjgRgJdUsGMG3Hf3OYSF/kHI79XhNlt+5Ar6OzwxQ== lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= + integrity sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ== lodash.uniqby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" - integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= + integrity sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww== lodash@^4.1.0, lodash@^4.15.0, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.2.0: version "4.17.21" @@ -5411,11 +6003,12 @@ log-update@^4.0.0: wrap-ansi "^6.2.0" logform@^2.3.2, logform@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.4.0.tgz#131651715a17d50f09c2a2c1a524ff1a4164bcfe" - integrity sha512-CPSJw4ftjf517EhXZGGvTHHkYobo7ZCc0kvwUoOYcjfR2UVrI66RHj8MCrfAdEitdmFqbu2BYdYs8FHHZSb6iw== + version "2.5.1" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.5.1.tgz#44c77c34becd71b3a42a3970c77929e52c6ed48b" + integrity sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg== dependencies: "@colors/colors" "1.5.0" + "@types/triple-beam" "^1.3.2" fecha "^4.2.0" ms "^2.1.1" safe-stable-stringify "^2.3.1" @@ -5426,6 +6019,11 @@ long@^4.0.0: resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== +long@^5.2.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== + loose-envify@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -5434,19 +6032,18 @@ loose-envify@^1.0.0: js-tokens "^3.0.0 || ^4.0.0" loupe@^2.3.1: - version "2.3.4" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" - integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== dependencies: get-func-name "^2.0.0" -lru-cache@^4.1.3: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" + yallist "^3.0.2" lru-cache@^6.0.0: version "6.0.0" @@ -5455,7 +6052,12 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -make-dir@^3.0.0, make-dir@^3.0.2: +lru-cache@^7.14.1: + version "7.18.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" + integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== + +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -5492,7 +6094,7 @@ make-fetch-happen@^9.0.1, make-fetch-happen@^9.1.0: map-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== map-obj@^4.0.0: version "4.3.0" @@ -5500,16 +6102,16 @@ map-obj@^4.0.0: integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== mariadb@^2.5.5: - version "2.5.5" - resolved "https://registry.yarnpkg.com/mariadb/-/mariadb-2.5.5.tgz#a9aff9f1e57231a415a21254489439beb501c803" - integrity sha512-6dklvcKWuuaV1JjAwnE2ezR+jTt7JrZHftgeHHBmjB0wgfaUpdxol1DPWclwMcCrsO9yoM0FuCOiCcCgXc//9Q== + version "2.5.6" + resolved "https://registry.yarnpkg.com/mariadb/-/mariadb-2.5.6.tgz#7314e9287cdba212831ebf16ef3b34dc6a1f0f06" + integrity sha512-zBx7loYY5GzLl8Y6AKxGXfY9DUYIIdGrmEORPOK9FEu0pg5ZLBKCGJuucHwKADxTBxKY7eM4rxndqxRcnMZKIw== dependencies: - "@types/geojson" "^7946.0.7" - "@types/node" "^14.14.28" - denque "^1.5.0" + "@types/geojson" "^7946.0.8" + "@types/node" "^17.0.10" + denque "^2.0.1" iconv-lite "^0.6.3" - long "^4.0.0" - moment-timezone "^0.5.33" + long "^5.2.0" + moment-timezone "^0.5.34" please-upgrade-node "^3.2.0" markdown-it@12.2.0: @@ -5580,7 +6182,7 @@ marked@^2.0.0: mdurl@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== meow@^8.0.0: version "8.1.2" @@ -5604,30 +6206,35 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== +micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.1" - picomatch "^2.2.3" + braces "^3.0.2" + picomatch "^2.3.1" -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.29, mime-types@~2.1.19: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== +mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.29, mime-types@~2.1.19: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "1.51.0" + mime-db "1.52.0" + +mime@^2.5.2: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== mime@^3.0.0: version "3.0.0" @@ -5649,20 +6256,27 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@3.0.4, minimatch@~3.0.4: +minimatch@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" +minimatch@~3.0.4: + version "3.0.8" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" + integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q== + dependencies: + brace-expansion "^1.1.7" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -5675,12 +6289,12 @@ minimist-options@4.1.0: minimist@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + integrity sha512-7Wl+Jz+IGWuSdgsQEJ4JunV0si/iMhg42MnQQG6h1R6TNeVenp4U9x5CC5v/gYqz/fENLQITAWXidNtVL0NNbw== -minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@~1.2.5: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minipass-collect@^1.0.2: version "1.0.2" @@ -5730,12 +6344,17 @@ minipass-sized@^1.0.3: minipass "^3.0.0" minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: - version "3.1.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" - integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== dependencies: yallist "^4.0.0" +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + minizlib@^2.0.0, minizlib@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" @@ -5753,13 +6372,20 @@ mkdirp-infer-owner@^2.0.0: infer-owner "^1.0.4" mkdirp "^1.0.3" -mkdirp@0.5.5, "mkdirp@>=0.5 0", mkdirp@^0.5.1: +mkdirp@0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" +"mkdirp@>=0.5 0", mkdirp@^0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" @@ -5795,40 +6421,32 @@ mocha@^7.2.0: yargs-parser "13.1.2" yargs-unparser "1.6.0" -mock-require@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/mock-require/-/mock-require-3.0.3.tgz#ccd544d9eae81dd576b3f219f69ec867318a1946" - integrity sha512-lLzfLHcyc10MKQnNUCv7dMcoY/2Qxd6wJfbqCcVk3LDb8An4hF6ohk5AztrvgKhJCqj36uyzi/p5se+tvyD+Wg== - dependencies: - get-caller-file "^1.0.2" - normalize-path "^2.1.1" - modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== module-alias@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0" - integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q== + version "2.2.3" + resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.3.tgz#ec2e85c68973bda6ab71ce7c93b763ec96053221" + integrity sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q== -moment-timezone@^0.5.15, moment-timezone@^0.5.33, moment-timezone@^0.5.34: - version "0.5.34" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c" - integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg== +moment-timezone@^0.5.15, moment-timezone@^0.5.34, moment-timezone@^0.5.43: + version "0.5.43" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.43.tgz#3dd7f3d0c67f78c23cd1906b9b2137a09b3c4790" + integrity sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ== dependencies: - moment ">= 2.9.0" + moment "^2.29.4" -"moment@>= 2.9.0", moment@^2.23.0, moment@^2.29.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== +moment@^2.29.4: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.1: version "2.1.1" @@ -5864,27 +6482,41 @@ mysql2@^2.3.3: seq-queue "^0.0.5" sqlstring "^2.3.2" +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + named-placeholders@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/named-placeholders/-/named-placeholders-1.1.2.tgz#ceb1fbff50b6b33492b5cf214ccf5e39cef3d0e8" - integrity sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA== + version "1.1.3" + resolved "https://registry.yarnpkg.com/named-placeholders/-/named-placeholders-1.1.3.tgz#df595799a36654da55dda6152ba7a137ad1d9351" + integrity sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w== dependencies: - lru-cache "^4.1.3" + lru-cache "^7.14.1" nan@^2.15.0: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== native-duplexpair@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/native-duplexpair/-/native-duplexpair-1.0.0.tgz#7899078e64bf3c8a3d732601b3d40ff05db58fa0" - integrity sha1-eJkHjmS/PIo9cyYBs9QP8F21j6A= + integrity sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA== + +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== negotiator@^0.6.2: version "0.6.3" @@ -5899,15 +6531,20 @@ neo-async@^2.6.0: nerf-dart@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/nerf-dart/-/nerf-dart-1.0.0.tgz#e6dab7febf5ad816ea81cf5c629c5a0ebde72c1a" - integrity sha1-5tq3/r9a2Bbqgc9cYpxaDr3nLBo= + integrity sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g== + +netmask@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" + integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== nise@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.0.tgz#713ef3ed138252daef20ec035ab62b7a28be645c" - integrity sha512-W5WlHu+wvo3PaKLsJJkgPup2LrsXCcm7AWwyNZkUnn5rwPkuPBi3Iwk5SQtN0mv+K65k7nKKjwNQ30wg3wLAQQ== + version "5.1.4" + resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.4.tgz#491ce7e7307d4ec546f5a659b2efe94a18b4bbc0" + integrity sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg== dependencies: - "@sinonjs/commons" "^1.7.0" - "@sinonjs/fake-timers" "^7.0.4" + "@sinonjs/commons" "^2.0.0" + "@sinonjs/fake-timers" "^10.0.2" "@sinonjs/text-encoding" "^0.7.1" just-extend "^4.0.2" path-to-regexp "^1.7.0" @@ -5932,13 +6569,34 @@ node-environment-flags@1.0.6: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" -node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== +node-fetch@^2.6.1, node-fetch@^2.6.7: + version "2.6.11" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" + integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== dependencies: whatwg-url "^5.0.0" +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + +node-gyp@8.x: + version "8.4.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" + integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.6" + make-fetch-happen "^9.1.0" + nopt "^5.0.0" + npmlog "^6.0.0" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.2" + which "^2.0.2" + node-gyp@^7.1.0, node-gyp@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae" @@ -5958,7 +6616,7 @@ node-gyp@^7.1.0, node-gyp@^7.1.2: node-hook@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-hook/-/node-hook-1.0.0.tgz#82ca39af991d726d5c7952e59c992378bb296f7e" - integrity sha1-gso5r5kdcm1ceVLlnJkjeLspb34= + integrity sha512-tBTIHwkzXvbesP0fY495VsqSWCOS5Ttt5+mAmeqUC1yglCiSYarNewfi2Q+HOL+M6pZYYqwGU6jIi5+gIHQbpg== node-preload@^0.2.1: version "0.2.1" @@ -5967,15 +6625,15 @@ node-preload@^0.2.1: dependencies: process-on-spawn "^1.0.0" -node-releases@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" - integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== +node-releases@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039" + integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ== noms@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/noms/-/noms-0.0.0.tgz#da8ebd9f3af9d6760919b27d9cdc8092a7332859" - integrity sha1-2o69nzr51nYJGbJ9nNyAkqczKFk= + integrity sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow== dependencies: inherits "^2.0.1" readable-stream "~1.0.31" @@ -6010,7 +6668,7 @@ normalize-package-data@^3.0.0, normalize-package-data@^3.0.2: normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== dependencies: remove-trailing-separator "^1.0.1" @@ -6213,10 +6871,20 @@ npmlog@^5.0.1: gauge "^3.0.0" set-blocking "^2.0.0" -nth-check@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== +npmlog@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" + integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.3" + set-blocking "^2.0.0" + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== dependencies: boolbase "^1.0.0" @@ -6230,7 +6898,7 @@ nth-check@~1.0.1: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== "nwmatcher@>= 1.3.7 < 2.0.0": version "1.4.4" @@ -6275,22 +6943,17 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== - -object-inspect@^1.11.1: - version "1.12.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" - integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== +object-inspect@^1.12.2, object-inspect@^1.12.3, object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.0.11, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -6305,40 +6968,31 @@ object.assign@4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.assign@^4.0.4, object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -object.getownpropertydescriptors@^2.0.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" - integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== +object.assign@^4.0.4, object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" -ocsp@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ocsp/-/ocsp-1.2.0.tgz#469a1776b457dee67eb0201408c1946bac4076cc" - integrity sha1-RpoXdrRX3uZ+sCAUCMGUa6xAdsw= +object.getownpropertydescriptors@^2.0.3: + version "2.1.6" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" + integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== dependencies: - asn1.js "^4.8.0" - asn1.js-rfc2560 "^4.0.0" - asn1.js-rfc5280 "^2.0.0" - async "^1.5.2" - simple-lru-cache "0.0.2" + array.prototype.reduce "^1.0.5" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.21.2" + safe-array-concat "^1.0.0" once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" @@ -6393,13 +7047,33 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +oracledb@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/oracledb/-/oracledb-5.5.0.tgz#0cf9af5d0c0815f74849ae9ed56aee823514d71b" + integrity sha512-i5cPvMENpZP8nnqptB6l0pjiOyySj1IISkbM4Hr3yZEDdANo2eezarwZb9NQ8fTh5pRjmgpZdSyIbnn9N3AENw== + ordered-read-streams@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" - integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= + integrity sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw== dependencies: readable-stream "^2.0.1" +os-name@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/os-name/-/os-name-1.0.3.tgz#1b379f64835af7c5a7f498b357cb95215c159edf" + integrity sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew== + dependencies: + osx-release "^1.0.0" + win-release "^1.0.0" + +osx-release@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/osx-release/-/osx-release-1.1.0.tgz#f217911a28136949af1bf9308b241e2737d3cd6c" + integrity sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A== + dependencies: + minimist "^1.1.0" + p-each-series@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" @@ -6431,7 +7105,7 @@ p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.2: dependencies: p-try "^2.0.0" -p-limit@^3.0.2: +p-limit@^3.0.1, p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -6441,7 +7115,7 @@ p-limit@^3.0.2: p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== dependencies: p-limit "^1.1.0" @@ -6502,14 +7176,6 @@ p-reflect@^2.1.0: resolved "https://registry.yarnpkg.com/p-reflect/-/p-reflect-2.1.0.tgz#5d67c7b3c577c4e780b9451fc9129675bd99fe67" integrity sha512-paHV8NUz8zDHu5lhr/ngGWQiW067DK/+IbJ+RfZ4k+s8y4EKyYCz8pGYWjxCg35eHztpJAt+NUgvN4L+GCbPlg== -p-retry@^4.0.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" - integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== - dependencies: - "@types/retry" "^0.12.0" - retry "^0.13.1" - p-settle@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/p-settle/-/p-settle-4.1.1.tgz#37fbceb2b02c9efc28658fc8d36949922266035f" @@ -6526,13 +7192,37 @@ p-timeout@^4.0.0: p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +pac-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz#b718f76475a6a5415c2efbe256c1c971c84f635e" + integrity sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + get-uri "3" + http-proxy-agent "^4.0.1" + https-proxy-agent "5" + pac-resolver "^5.0.0" + raw-body "^2.2.0" + socks-proxy-agent "5" + +pac-resolver@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-5.0.1.tgz#c91efa3a9af9f669104fa2f51102839d01cde8e7" + integrity sha512-cy7u00ko2KVgBAjuhevqpPeHIkCIqPe1v24cydhWjmeuzaBfmUWFCZJ1iAh5TuVzVZoUzXIW7K8sMYOZ84uZ9Q== + dependencies: + degenerator "^3.0.2" + ip "^1.1.5" + netmask "^2.0.2" + package-hash@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" @@ -6592,7 +7282,7 @@ parse-conflict-json@^1.1.1: parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== dependencies: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" @@ -6610,19 +7300,20 @@ parse-json@^5.0.0: parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== -parse5-htmlparser2-tree-adapter@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" - integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" + integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== dependencies: - parse5 "^6.0.1" + domhandler "^5.0.2" + parse5 "^7.0.0" parse5@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" - integrity sha1-m387DeMr543CQBsXVzzK8Pb1nZQ= + integrity sha512-w2jx/0tJzvgKwZa58sj2vAYq/S/K1QJfIB3cWYea/Iu1scFPDQQ3IQiVZTHWtRBwAjv2Yd7S/xeZf3XqLDb3bA== parse5@^3.0.1: version "3.0.3" @@ -6631,20 +7322,22 @@ parse5@^3.0.1: dependencies: "@types/node" "*" -parse5@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +parse5@^7.0.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" @@ -6654,7 +7347,7 @@ path-exists@^4.0.0: path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" @@ -6683,15 +7376,32 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== +pause-stream@~0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== + dependencies: + through "~2.3" + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== -pg-connection-string@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34" - integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ== +pg-cloudflare@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.0.tgz#833d70870d610d14bf9df7afb40e1cba310c17a0" + integrity sha512-tGM8/s6frwuAIyRcJ6nWcIvd3+3NmUKIs6OjviIm1HPPFEt5MzQDOTBQyhPWg/m0kCl95M6gA1JaIXtS8KovOA== + +pg-connection-string@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.0.tgz#12a36cc4627df19c25cc1b9b736cc39ee1f73ae8" + integrity sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg== + +pg-connection-string@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.1.tgz#78c23c21a35dd116f48e12e23c0965e8d9e2cbfb" + integrity sha512-w6ZzNu6oMmIzEAYVw+RLK0+nqHPt8K3ZnknKi+g48Ak2pr3dtljJW3o+D/n2zzCG07Zoe9VOX3aiKpj+BN0pjg== pg-hstore@^2.3.4: version "2.3.4" @@ -6705,15 +7415,15 @@ pg-int8@1.0.1: resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== -pg-pool@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.4.1.tgz#0e71ce2c67b442a5e862a9c182172c37eda71e9c" - integrity sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ== +pg-pool@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.0.tgz#3190df3e4747a0d23e5e9e8045bcd99bda0a712e" + integrity sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ== -pg-protocol@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.5.0.tgz#b5dd452257314565e2d54ab3c132adc46565a6a0" - integrity sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ== +pg-protocol@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.0.tgz#4c91613c0315349363af2084608db843502f8833" + integrity sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q== pg-types@^2.1.0: version "2.2.0" @@ -6727,44 +7437,51 @@ pg-types@^2.1.0: postgres-interval "^1.1.0" pg@^8.7.1: - version "8.7.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.7.1.tgz#9ea9d1ec225980c36f94e181d009ab9f4ce4c471" - integrity sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA== + version "8.11.0" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.0.tgz#a37e534e94b57a7ed811e926f23a7c56385f55d9" + integrity sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA== dependencies: buffer-writer "2.0.0" packet-reader "1.0.0" - pg-connection-string "^2.5.0" - pg-pool "^3.4.1" - pg-protocol "^1.5.0" + pg-connection-string "^2.6.0" + pg-pool "^3.6.0" + pg-protocol "^1.6.0" pg-types "^2.1.0" pgpass "1.x" + optionalDependencies: + pg-cloudflare "^1.1.0" pgpass@1.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.4.tgz#85eb93a83800b20f8057a2b029bf05abaf94ea9c" - integrity sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w== + version "1.0.5" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" + integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== dependencies: - split2 "^3.1.1" + split2 "^4.1.0" picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== +picomatch@^2.0.4, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pidtree@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.5.0.tgz#ad5fbc1de78b8a5f99d6fbdd4f6e4eee21d1aca1" + integrity sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA== pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== pkg-conf@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-2.1.0.tgz#2126514ca6f2abfebd168596df18ba57867f0058" - integrity sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg= + integrity sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g== dependencies: find-up "^2.0.0" load-json-file "^4.0.0" @@ -6791,7 +7508,7 @@ postgres-array@~2.0.0: postgres-bytea@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" - integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= + integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== postgres-date@~1.0.4: version "1.0.7" @@ -6813,7 +7530,7 @@ prelude-ls@^1.2.1: prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== proc-log@^1.0.0: version "1.0.0" @@ -6835,12 +7552,7 @@ process-on-spawn@^1.0.0: process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== promise-all-reject-late@^1.0.0: version "1.0.1" @@ -6848,14 +7560,14 @@ promise-all-reject-late@^1.0.0: integrity sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw== promise-call-limit@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-call-limit/-/promise-call-limit-1.0.1.tgz#4bdee03aeb85674385ca934da7114e9bcd3c6e24" - integrity sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q== + version "1.0.2" + resolved "https://registry.yarnpkg.com/promise-call-limit/-/promise-call-limit-1.0.2.tgz#f64b8dd9ef7693c9c7613e7dfe8d6d24de3031ea" + integrity sha512-1vTUnfI2hzui8AEIixbdAJlFY4LFDXqQswy/2eOlThAscXCY4It8FdVuI0fMJGAB2aWGbdQf/gv0skKYXmdrHA== promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== promise-retry@^2.0.1: version "2.0.1" @@ -6868,19 +7580,33 @@ promise-retry@^2.0.1: promzard@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" - integrity sha1-JqXW7ox97kyxIggwWs+5O6OCqe4= + integrity sha512-JZeYqd7UAcHCwI+sTOeUDYkvEU+1bQ7iE0UT1MgB/tERkAPkesW46MrpIySzODi+owTjZtiF8Ay5j9m60KmMBw== dependencies: read "1" -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= +proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-5.0.0.tgz#d31405c10d6e8431fde96cba7a0c027ce01d633b" + integrity sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g== + dependencies: + agent-base "^6.0.0" + debug "4" + http-proxy-agent "^4.0.0" + https-proxy-agent "^5.0.0" + lru-cache "^5.1.1" + pac-proxy-agent "^5.0.0" + proxy-from-env "^1.0.0" + socks-proxy-agent "^5.0.0" -psl@^1.1.28, psl@^1.1.33: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== +proxy-from-env@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +psl@^1.1.28: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== pump@^1.0.0: version "1.0.3" @@ -6898,6 +7624,14 @@ pump@^2.0.0: end-of-stream "^1.1.0" once "^1.3.1" +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + pumpify@^1.3.5: version "1.5.1" resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" @@ -6910,12 +7644,12 @@ pumpify@^1.3.5: punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== python-struct@^1.1.3: version "1.1.3" @@ -6927,22 +7661,29 @@ python-struct@^1.1.3: q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== qrcode-terminal@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== +qs@^6.4.0: + version "6.11.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" + integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== + dependencies: + side-channel "^1.0.4" + qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== queue-microtask@^1.2.2: version "1.2.3" @@ -6955,11 +7696,21 @@ quick-lru@^4.0.1: integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== ramda@^0.27.1: - version "0.27.1" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" - integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== + version "0.27.2" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.2.tgz#84463226f7f36dc33592f6f4ed6374c48306c3f1" + integrity sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA== -rc@^1.2.8: +raw-body@^2.2.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@1.2.8, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -6983,9 +7734,9 @@ read-package-json-fast@^2.0.1, read-package-json-fast@^2.0.2, read-package-json- npm-normalize-package-bin "^1.0.1" read-package-json@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-4.1.1.tgz#153be72fce801578c1c86b8ef2b21188df1b9eea" - integrity sha512-P82sbZJ3ldDrWCOSKxJT0r/CXMWR0OR3KRh55SgKo3p91GSIEEC32v3lSHAvO/UcH3/IoL7uqhOFBduAnwdldw== + version "4.1.2" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-4.1.2.tgz#b444d047de7c75d4a160cb056d00c0693c1df703" + integrity sha512-Dqer4pqzamDE2O4M55xp1qZMuLPqi4ldk2ya648FOMHRjwMzFhuxVrG04wd0c38IsvkVdr3vgHI6z+QTPdAjrQ== dependencies: glob "^7.1.1" json-parse-even-better-errors "^2.3.0" @@ -7014,14 +7765,24 @@ read-pkg@^5.0.0, read-pkg@^5.2.0: read@1, read@^1.0.7, read@~1.0.1, read@~1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" - integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= + integrity sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ== dependencies: mute-stream "~0.0.4" readable-stream@1.1: version "1.1.13" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" - integrity sha1-9u73ZPUUyJ4rniMUanW6EGdW0j4= + integrity sha512-E98tWzqShvKDGpR2MbjsDkDQWLW2TfWUC15H4tNQhIJ5Lsta84l8nUGL9/ybltGwe+wZzWPpc1Kmd2wQP4bdCA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@1.1.x: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -7029,18 +7790,18 @@ readable-stream@1.1: string_decoder "~0.10.x" readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.1, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -7053,7 +7814,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable readable-stream@~1.0.31: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -7088,7 +7849,7 @@ redent@^3.0.0: redeyed@~2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-2.1.1.tgz#8984b5815d99cb220469c99eeeffe38913e6cc0b" - integrity sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs= + integrity sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ== dependencies: esprima "~4.0.0" @@ -7097,10 +7858,14 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== +regexp.prototype.flags@^1.4.3: + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + functions-have-names "^1.2.3" regextras@^0.8.0: version "0.8.0" @@ -7108,16 +7873,16 @@ regextras@^0.8.0: integrity sha512-k519uI04Z3SaY0fLX843MRXnDeG2+vHOFsyhiPZvNLe7r8rD2YNRjq4BQLZZ0oAr2NrtvZlICsXysGNFPGa3CQ== registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + version "4.2.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" + integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== dependencies: - rc "^1.2.8" + rc "1.2.8" release-zalgo@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" - integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= + integrity sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA== dependencies: es6-error "^4.0.1" @@ -7132,7 +7897,7 @@ remove-bom-buffer@^3.0.0: remove-bom-stream@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" - integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= + integrity sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA== dependencies: remove-bom-buffer "^3.0.0" safe-buffer "^5.1.0" @@ -7141,19 +7906,19 @@ remove-bom-stream@^1.2.0: remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== repeating@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac" - integrity sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw= + integrity sha512-Nh30JLeMHdoI+AsQ5eblhZ7YlTsM9wiJQe/AHIunlK3KWzvXhXb36IJ7K1IOeRjIOtzMjdUHjwXUFxKJoPTSOg== dependencies: is-finite "^1.0.0" repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== dependencies: is-finite "^1.0.0" @@ -7188,18 +7953,10 @@ replace-ext@^1.0.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -requestretry@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/requestretry/-/requestretry-6.0.0.tgz#a213b2133ee3b18f74c2bbc0f4e094e561b57335" - integrity sha512-X7O+BMlfHgzetfSDtgQIMinLn1BuT+95W12iffDzyOS+HLoBEIQqCZv++UTChUWVjOu+pudbocD76+4j+jK9ww== - dependencies: - extend "^3.0.2" - lodash "^4.17.15" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-main-filename@^2.0.0: version "2.0.0" @@ -7226,16 +7983,16 @@ resolve-global@1.0.0, resolve-global@^1.0.0: resolve-options@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" - integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= + integrity sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A== dependencies: value-or-function "^3.0.0" resolve@^1.10.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== dependencies: - is-core-module "^2.8.1" + is-core-module "^2.11.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -7247,21 +8004,29 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -retry-as-promised@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-5.0.0.tgz#f4ecc25133603a2d2a7aff4a128691d7bc506d54" - integrity sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA== +retry-as-promised@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-7.0.4.tgz#9df73adaeea08cb2948b9d34990549dc13d800a2" + integrity sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA== -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +retry-request@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-5.0.2.tgz#143d85f90c755af407fcc46b7166a4ba520e44da" + integrity sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ== + dependencies: + debug "^4.1.1" + extend "^3.0.2" -retry@^0.13.1: +retry@0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -7287,13 +8052,13 @@ rimraf@^3.0.0, rimraf@^3.0.2: glob "^7.1.3" run-con@~1.2.10: - version "1.2.10" - resolved "https://registry.yarnpkg.com/run-con/-/run-con-1.2.10.tgz#90de9d43d20274d00478f4c000495bd72f417d22" - integrity sha512-n7PZpYmMM26ZO21dd8y3Yw1TRtGABjRtgPSgFS/nhzfvbJMXFtJhJVyEgayMiP+w/23craJjsnfDvx4W4ue/HQ== + version "1.2.11" + resolved "https://registry.yarnpkg.com/run-con/-/run-con-1.2.11.tgz#0014ed430bad034a60568dfe7de2235f32e3f3c4" + integrity sha512-NEMGsUT+cglWkzEr4IFK21P4Jca45HqiAbIIZIBdX5+UZTB24Mb/21iNGgz9xZa8tL6vbW7CXmq7MFN42+VjNQ== dependencies: deep-extend "^0.6.0" - ini "~2.0.0" - minimist "^1.2.5" + ini "~3.0.0" + minimist "^1.2.6" strip-json-comments "~3.1.1" run-parallel@^1.1.9: @@ -7303,12 +8068,22 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^7.4.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.4.0.tgz#a12a44d7eebf016f5ff2441b87f28c9a51cebc68" - integrity sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w== +rxjs@^7.5.5: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + +safe-array-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" + integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== dependencies: - tslib "~2.1.0" + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + has-symbols "^1.0.3" + isarray "^2.0.5" safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.1" @@ -7320,10 +8095,19 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + safe-stable-stringify@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz#ab67cbe1fe7d40603ca641c5e765cb942d04fc73" - integrity sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg== + version "2.4.3" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" @@ -7333,7 +8117,7 @@ safe-stable-stringify@^2.3.1: sax@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" - integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= + integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== sax@>=0.6.0, sax@^1.1.4: version "1.2.4" @@ -7382,7 +8166,7 @@ semantic-release@^18.0.1: semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" - integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== semver-diff@^3.1.1: version "3.1.1" @@ -7392,16 +8176,16 @@ semver-diff@^3.1.1: semver "^6.3.0" semver-regex@^3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.3.tgz#b2bcc6f97f63269f286994e297e229b6245d0dc3" - integrity sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ== + version "3.1.4" + resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.4.tgz#13053c0d4aa11d070a2f2872b6b1e3ae1e1971b4" + integrity sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA== -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.4.1, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@7.3.5, semver@^7.1.1, semver@^7.1.2, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: +semver@7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -7413,10 +8197,24 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.1.1, semver@^7.1.2, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: + version "7.5.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.2.tgz#5b851e66d1be07c1cdaf37dfc856f543325a2beb" + integrity sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ== + dependencies: + lru-cache "^6.0.0" + +semver@^7.1.3, semver@^7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" - integrity sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4= + integrity sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q== sequelize-pool@^7.1.0: version "7.1.0" @@ -7426,12 +8224,17 @@ sequelize-pool@^7.1.0: set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== setimmediate@~1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== shebang-command@^2.0.0: version "2.0.0" @@ -7459,7 +8262,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -7473,15 +8276,15 @@ signale@^1.2.1: figures "^2.0.0" pkg-conf "^2.1.0" -simple-lru-cache@0.0.2, simple-lru-cache@^0.0.2: +simple-lru-cache@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz#d59cc3a193c1a5d0320f84ee732f6e4713e511dd" - integrity sha1-1ZzDoZPBpdAyD4Tucy9uRxPlEd0= + integrity sha512-uEv/AFO0ADI7d99OHDmh1QfYzQk/izT1vCmu/riQfh7qjBVUUgRT87E5s5h7CxWCA/+YoZerykpEthzVrW3LIw== simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== dependencies: is-arrayish "^0.3.1" @@ -7539,63 +8342,70 @@ smart-buffer@^4.2.0: integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== snowflake-sdk@^1.6.6: - version "1.6.6" - resolved "https://registry.yarnpkg.com/snowflake-sdk/-/snowflake-sdk-1.6.6.tgz#7ab8a1abc0a73b1e7a1c73ffe341310b83a7cb57" - integrity sha512-b8mbYI6TFGe8H0m0eviNd4FC/3jsw02OHNt21k9sLWkBp4re2VUhaJf7555ln7thMSnMcbkdAB8zQBZcbqdoPg== + version "1.6.23" + resolved "https://registry.yarnpkg.com/snowflake-sdk/-/snowflake-sdk-1.6.23.tgz#f6b16bcfce1fadaa0b2c51d8aabaaa6f1bf4b5d2" + integrity sha512-meKcFQ2NggyhItmZ019JJ5UAeQiN0n98P7plAhM9DjVvI04JngvprUsmluu7c6Ujo/IYQC6jC8/7+cmgiMC7Bw== dependencies: - "@azure/storage-blob" "^12.5.0" - agent-base "^4.3.0" + "@azure/storage-blob" "^12.11.0" + "@google-cloud/storage" "^6.9.3" + "@techteamer/ocsp" "1.0.0" + agent-base "^6.0.2" asn1.js-rfc2560 "^5.0.0" asn1.js-rfc5280 "^3.0.0" + async "^3.2.3" aws-sdk "^2.878.0" - axios "^0.21.4" + axios "^0.27.2" + better-eval "^1.3.0" big-integer "^1.6.43" bignumber.js "^2.4.0" binascii "0.0.2" + bn.js "^5.2.1" browser-request "^0.3.3" debug "^3.2.6" expand-tilde "^2.0.2" extend "^3.0.2" + fast-xml-parser "^4.1.3" generic-pool "^3.8.2" glob "^7.1.6" - http-signature "^1.3.6" - https-proxy-agent "^3.0.0" - json-schema "^0.4.0" - jsonwebtoken "^8.5.1" - jsprim "^2.0.2" - lodash "^4.17.21" + https-proxy-agent "^5.0.1" + jsonwebtoken "^9.0.0" mime-types "^2.1.29" mkdirp "^1.0.3" - mock-require "^3.0.3" - moment "^2.23.0" + moment "^2.29.4" moment-timezone "^0.5.15" - ocsp "^1.2.0" open "^7.3.1" python-struct "^1.1.3" - request "^2.88.2" - requestretry "^6.0.0" simple-lru-cache "^0.0.2" string-similarity "^4.0.4" - test-console "^2.0.0" tmp "^0.2.1" + urllib "^2.38.0" uuid "^3.3.2" winston "^3.1.0" +socks-proxy-agent@5, socks-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz#032fb583048a29ebffec2e6a73fca0761f48177e" + integrity sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ== + dependencies: + agent-base "^6.0.2" + debug "4" + socks "^2.3.3" + socks-proxy-agent@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" - integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== + version "6.2.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz#2687a31f9d7185e38d530bef1944fe1f1496d6ce" + integrity sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ== dependencies: agent-base "^6.0.2" - debug "^4.3.1" - socks "^2.6.1" + debug "^4.3.3" + socks "^2.6.2" -socks@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a" - integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== +socks@^2.3.3, socks@^2.6.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" + integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== dependencies: - ip "^1.1.5" + ip "^2.0.0" smart-buffer "^4.2.0" source-map-support@^0.5.17, source-map-support@^0.5.21: @@ -7609,7 +8419,7 @@ source-map-support@^0.5.17, source-map-support@^0.5.21: source-map@^0.5.0, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" @@ -7619,7 +8429,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: spawn-error-forwarder@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz#1afd94738e999b0346d7b9fc373be55e07577029" - integrity sha1-Gv2Uc46ZmwNG17n8NzvlXgdXcCk= + integrity sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g== spawn-wrap@^2.0.0: version "2.0.0" @@ -7634,9 +8444,9 @@ spawn-wrap@^2.0.0: which "^2.0.1" spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -7655,21 +8465,26 @@ spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.11" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" - integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + version "3.0.13" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" + integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== -split2@^3.0.0, split2@^3.1.1: +split2@^3.0.0: version "3.2.2" resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== dependencies: readable-stream "^3.0.0" +split2@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + split2@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/split2/-/split2-1.0.0.tgz#52e2e221d88c75f9a73f90556e263ff96772b314" - integrity sha1-UuLiIdiMdfmnP5BVbiY/+WdysxQ= + integrity sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg== dependencies: through2 "~2.0.0" @@ -7688,24 +8503,28 @@ sprintf-js@^1.1.2: sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -"sqlite3@npm:@vscode/sqlite3@^5.0.7": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@vscode/sqlite3/-/sqlite3-5.0.7.tgz#358df36bb0e9e735c54785e3e4b9b2dce1d32895" - integrity sha512-NlsOf+Hir2r4zopI1qMvzWXPwPJuFscirkmFTniTAT24Yz2FWcyZxzK7UT8iSNiTqOCPz48yF55ZVHaz7tTuVQ== +sqlite3@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.6.tgz#1d4fbc90fe4fbd51e952e0a90fd8f6c2b9098e97" + integrity sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw== dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" node-addon-api "^4.2.0" + tar "^6.1.11" + optionalDependencies: + node-gyp "8.x" sqlstring@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.2.tgz#cdae7169389a1375b18e885f2e60b3e460809514" - integrity sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg== + version "2.3.3" + resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.3.tgz#2ddc21f03bce2c387ed60680e739922c65751d0c" + integrity sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg== -sshpk@^1.14.1, sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -7727,30 +8546,47 @@ ssri@^8.0.0, ssri@^8.0.1: stack-chain@^1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" - integrity sha1-0ZLJ/06moiyUxN1FkXHj8AzqEoU= + integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +statuses@^1.3.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== stream-combiner2@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" - integrity sha1-+02KFCDqNidk4hrUeAOXvry0HL4= + integrity sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw== dependencies: duplexer2 "~0.1.0" readable-stream "^2.0.2" +stream-events@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" + integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== + dependencies: + stubs "^3.0.0" + stream-shift@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== string-argv@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" - integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== + version "0.3.2" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" + integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== string-similarity@^4.0.4: version "4.0.4" @@ -7760,13 +8596,13 @@ string-similarity@^4.0.4: string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.1 || ^2.0.0", "string-width@^1.0.2 || 2", string-width@^2.0.0: +"string-width@^1.0.2 || 2", string-width@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -7774,7 +8610,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -7793,29 +8629,40 @@ string-width@^3.0.0, string-width@^3.1.0: strip-ansi "^5.1.0" string-width@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.0.1.tgz#0d8158335a6cfd8eb95da9b6b262ce314a036ffd" - integrity sha512-5ohWO/M4//8lErlUUtrFy3b11GtNOuMOU0ysKCDXFcfXuuvUXu95akgj/i8ofmaGdN0hCqyl6uu9i8dS/mQp5g== + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== dependencies: + eastasianwidth "^0.2.0" emoji-regex "^9.2.2" - is-fullwidth-code-point "^4.0.0" strip-ansi "^7.0.1" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.20.4" -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" string_decoder@^1.1.1: version "1.3.0" @@ -7827,7 +8674,7 @@ string_decoder@^1.1.1: string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== string_decoder@~1.1.1: version "1.1.1" @@ -7844,14 +8691,14 @@ stringify-package@^1.0.1: strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== dependencies: ansi-regex "^2.0.0" -"strip-ansi@^3.0.1 || ^4.0.0", strip-ansi@^4.0.0: +strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== dependencies: ansi-regex "^3.0.0" @@ -7870,16 +8717,16 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: ansi-regex "^5.0.1" strip-ansi@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== dependencies: ansi-regex "^6.0.1" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-bom@^4.0.0: version "4.0.0" @@ -7901,13 +8748,23 @@ strip-indent@^3.0.0: strip-json-comments@2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== strip-json-comments@^3.1.0, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + +stubs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" + integrity sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw== + supports-color@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" @@ -7918,7 +8775,7 @@ supports-color@6.0.0: supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== supports-color@^5.3.0: version "5.5.0" @@ -7934,15 +8791,15 @@ supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0: dependencies: has-flag "^4.0.0" -supports-color@^9.2.1: - version "9.2.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.2.1.tgz#599dc9d45acf74c6176e0d880bab1d7d718fe891" - integrity sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ== +supports-color@^9.2.2: + version "9.3.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.3.1.tgz#34e4ad3c71c9a39dae3254ecc46c9b74e89e15a6" + integrity sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q== supports-hyperlinks@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" - integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== dependencies: has-flag "^4.0.0" supports-color "^7.0.0" @@ -7960,12 +8817,12 @@ supports-preserve-symlinks-flag@^1.0.0: taffydb@2.7.2: version "2.7.2" resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.7.2.tgz#7bf8106a5c1a48251b3e3bc0a0e1732489fd0dc8" - integrity sha1-e/gQalwaSCUbPjvAoOFzJIn9Dcg= + integrity sha512-R6es6/C/m1xXZckrSam4j07YKbd74437mRJ/R944S1hLG7mIl2/EQW7tQPI4XiX7jTduFzz31g7466a2BcsglQ== taffydb@2.7.3: version "2.7.3" resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.7.3.tgz#2ad37169629498fca5bc84243096d3cde0ec3a34" - integrity sha1-KtNxaWKUmPylvIQkMJbTzeDsOjQ= + integrity sha512-GQ3gtYFSOAxSMN/apGtDKKkbJf+8izz5YfbGqIsUc7AMiQOapARZ76dhilRY2h39cynYxBFdafQo5HUL5vgkrg== tar-fs@^1.8.1: version "1.16.3" @@ -7990,14 +8847,14 @@ tar-stream@^1.1.2: to-buffer "^1.1.1" xtend "^4.0.0" -tar@^6.0.2, tar@^6.1.0, tar@^6.1.11: - version "6.1.11" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" - integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== +tar@^6.0.2, tar@^6.1.0, tar@^6.1.11, tar@^6.1.2: + version "6.1.15" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.15.tgz#c9738b0b98845a3b344d334b8fa3041aaba53a69" + integrity sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" - minipass "^3.0.0" + minipass "^5.0.0" minizlib "^2.1.1" mkdirp "^1.0.3" yallist "^4.0.0" @@ -8005,7 +8862,7 @@ tar@^6.0.2, tar@^6.1.0, tar@^6.1.11: targz@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/targz/-/targz-1.0.1.tgz#8f76a523694cdedfbb5d60a4076ff6eeecc5398f" - integrity sha1-j3alI2lM3t+7XWCkB2/27uzFOY8= + integrity sha512-6q4tP9U55mZnRuMTBqnqc3nwYQY3kv+QthCFZuMk+Tn1qYUnMPmL/JZ/mzgXINzFpSqfU+242IFmFU9VPvqaQw== dependencies: tar-fs "^1.8.1" @@ -8025,6 +8882,17 @@ tedious@8.3.0: readable-stream "^3.6.0" sprintf-js "^1.1.2" +teeny-request@^8.0.0: + version "8.0.3" + resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-8.0.3.tgz#5cb9c471ef5e59f2fca8280dc3c5909595e6ca24" + integrity sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww== + dependencies: + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + node-fetch "^2.6.1" + stream-events "^1.0.5" + uuid "^9.0.0" + temp-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" @@ -8041,11 +8909,6 @@ tempy@^1.0.0: type-fest "^0.16.0" unique-string "^2.0.0" -test-console@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/test-console/-/test-console-2.0.0.tgz#a279f7e2e148815224d8446ffa5208f0077d68fb" - integrity sha512-ciILzfCQCny8zy1+HEw2yBLKus7LNMsAHymsp2fhvGTVh5pWE5v2EB7V+5ag3WM9aO2ULtgsXVQePWYE+fb7pA== - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -8068,7 +8931,21 @@ text-hex@1.0.x: text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" through2-filter@^3.0.0: version "3.0.0" @@ -8093,10 +8970,10 @@ through2@^4.0.0: dependencies: readable-stream "3" -through@2, "through@>=2.2.7 <3", through@^2.3.8: +through@2, "through@>=2.2.7 <3", through@^2.3.8, through@~2.3: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== tiny-relative-date@^1.3.0: version "1.3.0" @@ -8113,7 +8990,7 @@ tmp@^0.2.1: to-absolute-glob@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" - integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= + integrity sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA== dependencies: is-absolute "^1.0.0" is-negated-glob "^1.0.0" @@ -8126,12 +9003,12 @@ to-buffer@^1.1.1: to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-regex-range@^5.0.1: version "5.0.1" @@ -8143,14 +9020,19 @@ to-regex-range@^5.0.1: to-through@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" - integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= + integrity sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q== dependencies: through2 "^2.0.3" +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + toposort-class@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988" - integrity sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg= + integrity sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg== tough-cookie@^2.2.0, tough-cookie@^2.4.3, tough-cookie@~2.5.0: version "2.5.0" @@ -8160,29 +9042,20 @@ tough-cookie@^2.2.0, tough-cookie@^2.4.3, tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" -tough-cookie@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" - integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.1.2" - tr46@~0.0.1, tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== "traverse@>=0.3.0 <0.4": version "0.3.9" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" - integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk= + integrity sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ== traverse@~0.6.6: - version "0.6.6" - resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" - integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= + version "0.6.7" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.7.tgz#46961cd2d57dd8706c36664acde06a248f1173fe" + integrity sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg== treeverse@^1.0.4: version "1.0.4" @@ -8197,7 +9070,7 @@ trim-newlines@^3.0.0: trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= + integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== triple-beam@^1.3.0: version "1.3.0" @@ -8221,15 +9094,10 @@ tslib@^1.8.1, tslib@^1.9.2: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2, tslib@^2.0.0, tslib@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - -tslib@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" - integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== +tslib@^2, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.2.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" + integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== tsutils@^3.21.0: version "3.21.0" @@ -8241,7 +9109,7 @@ tsutils@^3.21.0: tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" @@ -8253,7 +9121,7 @@ tunnel@0.0.6, tunnel@^0.0.6: tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" @@ -8265,7 +9133,7 @@ type-check@^0.4.0, type-check@~0.4.0: type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== dependencies: prelude-ls "~1.1.2" @@ -8304,6 +9172,15 @@ type-fest@^0.8.0, type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -8311,15 +9188,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@^4.4.3: - version "4.5.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" - integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== - -typescript@^4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8" - integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg== +typescript@^4.4.3, typescript@^4.5.4: + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" @@ -8327,29 +9199,36 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== uglify-js@^3.1.4: - version "3.15.1" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.1.tgz#9403dc6fa5695a6172a91bc983ea39f0f7c9086d" - integrity sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ== + version "3.17.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + integrity sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg== "underscore@>= 1.3.1", underscore@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.1.tgz#0c1c6bd2df54b6b69f2314066d65b6cde6fcf9d1" - integrity sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g== + version "1.13.6" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" + integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== + +unescape@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unescape/-/unescape-1.0.1.tgz#956e430f61cad8a4d57d82c518f5e6cc5d0dda96" + integrity sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ== + dependencies: + extend-shallow "^2.0.1" unique-filename@^1.1.1: version "1.1.1" @@ -8385,7 +9264,7 @@ universal-user-agent@^6.0.0: resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== -universalify@^0.1.0, universalify@^0.1.2: +universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== @@ -8395,15 +9274,20 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +unpipe@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== unzipper@^0.10.11: - version "0.10.11" - resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.10.11.tgz#0b4991446472cbdb92ee7403909f26c2419c782e" - integrity sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw== + version "0.10.14" + resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.10.14.tgz#d2b33c977714da0fbc0f82774ad35470a7c962b1" + integrity sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g== dependencies: big-integer "^1.6.17" binary "~0.3.0" @@ -8416,6 +9300,14 @@ unzipper@^0.10.11: readable-stream "~2.3.6" setimmediate "~1.0.4" +update-browserslist-db@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -8431,35 +9323,78 @@ url-join@^4.0.0: url@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= + integrity sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ== dependencies: punycode "1.3.2" querystring "0.2.0" +urllib@^2.38.0: + version "2.40.0" + resolved "https://registry.yarnpkg.com/urllib/-/urllib-2.40.0.tgz#c63d4425081908560d7e1c4dc651f7d723a3cf76" + integrity sha512-XDZjoijtzsbkXTXgM+A/sJM002nwoYsc46YOYr6MNH2jUUw1nCBf2ywT1WaPsVEWJX4Yr+9isGmYj4+yofFn9g== + dependencies: + any-promise "^1.3.0" + content-type "^1.0.2" + debug "^2.6.9" + default-user-agent "^1.0.0" + digest-header "^1.0.0" + ee-first "~1.1.1" + formstream "^1.1.0" + humanize-ms "^1.2.0" + iconv-lite "^0.4.15" + ip "^1.1.5" + proxy-agent "^5.0.0" + pump "^3.0.0" + qs "^6.4.0" + statuses "^1.3.1" + utility "^1.16.1" + util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== +util@^0.12.4: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + +utility@^1.16.1: + version "1.18.0" + resolved "https://registry.yarnpkg.com/utility/-/utility-1.18.0.tgz#af55f62e6d5a272e0cb02b0ab3e7f37c46435f36" + integrity sha512-PYxZDA+6QtvRvm//++aGdmKG/cI07jNwbROz0Ql+VzFV1+Z0Dy55NI4zZ7RHc9KKpBePNFwoErqIuqQv/cjiTA== + dependencies: + copy-to "^2.0.1" + escape-html "^1.0.3" + mkdirp "^0.5.1" + mz "^2.7.0" + unescape "^1.0.1" -uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2, uuid@^3.3.3: +uuid@8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" + integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== + +uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.3.0, uuid@^8.3.2: +uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -v8-compile-cache@^2.0.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" - integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" @@ -8472,24 +9407,24 @@ validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" - integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= + integrity sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw== dependencies: builtins "^1.0.3" -validator@^13.7.0: - version "13.7.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857" - integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw== +validator@^13.9.0: + version "13.9.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855" + integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA== value-or-function@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" - integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= + integrity sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg== verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -8521,7 +9456,7 @@ vinyl-fs@^3.0.2: vinyl-sourcemap@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" - integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= + integrity sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA== dependencies: append-buffer "^1.0.2" convert-source-map "^1.5.0" @@ -8543,6 +9478,14 @@ vinyl@^2.0.0, vinyl@^2.1.0: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" +vm2@^3.9.17: + version "3.9.19" + resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.19.tgz#be1e1d7a106122c6c492b4d51c2e8b93d3ed6a4a" + integrity sha512-J637XF0DHDMV57R6JyVsTak7nIL8gy5KH4r1HiwWLf/4GBbb5MKL5y7LpmF4A8E2nR6XmzpmMFQ7V7ppPTmUQg== + dependencies: + acorn "^8.7.0" + acorn-walk "^8.2.0" + walk-up-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e" @@ -8551,31 +9494,31 @@ walk-up-path@^1.0.0: wcwidth@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== dependencies: defaults "^1.0.3" webidl-conversions@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-2.0.1.tgz#3bf8258f7d318c7443c36f2e169402a1a6703506" - integrity sha1-O/glj30xjHRDw28uFpQCoaZwNQY= + integrity sha512-OZ7I/f0sM+T28T2/OXinNGfmvjm3KKptdyQy8NPRZyLfYBn+9vt72Bfr+uQaE9OvWyxJjQ5kHFygH2wOTUb76g== webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== whatwg-url-compat@~0.6.5: version "0.6.5" resolved "https://registry.yarnpkg.com/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz#00898111af689bb097541cd5a45ca6c8798445bf" - integrity sha1-AImBEa9om7CXVBzVpFymyHmERb8= + integrity sha512-vbg5+JVNwGtHRI3GheZGWrcUlxF9BXHbA80dLa+2XqJjlV/BK6upoi2j8dIRW9FGPUUyaMm7Hf1pTexHnsk85g== dependencies: tr46 "~0.0.1" whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" @@ -8592,9 +9535,21 @@ which-boxed-primitive@^1.0.2: is-symbol "^1.0.3" which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + +which-typed-array@^1.1.2, which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" which@1.3.1: version "1.3.1" @@ -8617,13 +9572,20 @@ wide-align@1.1.3: dependencies: string-width "^1.0.2 || 2" -wide-align@^1.1.0, wide-align@^1.1.2: +wide-align@^1.1.0, wide-align@^1.1.2, wide-align@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: string-width "^1.0.2 || 2 || 3 || 4" +win-release@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/win-release/-/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209" + integrity sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw== + dependencies: + semver "^5.0.1" + winston-transport@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" @@ -8634,10 +9596,11 @@ winston-transport@^4.5.0: triple-beam "^1.3.0" winston@^3.1.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.6.0.tgz#be32587a099a292b88c49fac6fa529d478d93fb6" - integrity sha512-9j8T75p+bcN6D00sF/zjFVmPp+t8KMPB1MzbbzYjeN9VWxdsYnTB40TkbNUEXAmILEfChMvAMgidlX64OG3p6w== + version "3.9.0" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.9.0.tgz#2bbdeb8167a75fac6d9a0c6d002890cd908016c2" + integrity sha512-jW51iW/X95BCW6MMtZWr2jKQBP4hV5bIDq9QrIjfDk6Q9QuxvTKEAlpUNAzP+HYHFFCeENhph16s0zEunu4uuQ== dependencies: + "@colors/colors" "1.5.0" "@dabh/diagnostics" "^2.0.2" async "^3.2.3" is-stream "^2.0.0" @@ -8664,7 +9627,7 @@ word-wrap@^1.2.3, word-wrap@~1.2.3: wordwrap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== wrap-ansi@^5.1.0: version "5.1.0" @@ -8696,7 +9659,7 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: version "3.0.3" @@ -8711,15 +9674,15 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: "xml-name-validator@>= 2.0.1 < 3.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" - integrity sha1-TYuPHszTQZqjYgYb7O9RXh5VljU= + integrity sha512-jRKe/iQYMyVJpzPH+3HL97Lgu5HrCfii+qSo+TfjKHtOnvbnvdVfMYrn9Q34YV81M2e5sviJlI6Ko9y+nByzvA== -xml2js@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== +xml2js@0.5.0, xml2js@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== dependencies: sax ">=0.6.0" - xmlbuilder "~9.0.1" + xmlbuilder "~11.0.0" xml2js@^0.4.19: version "0.4.23" @@ -8734,11 +9697,6 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== -xmlbuilder@~9.0.1: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= - "xmldom@>= 0.1.x": version "0.6.0" resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.6.0.tgz#43a96ecb8beece991cef382c08397d82d4d0c46f" @@ -8749,6 +9707,11 @@ xpath.js@~1.1.0: resolved "https://registry.yarnpkg.com/xpath.js/-/xpath.js-1.1.0.tgz#3816a44ed4bb352091083d002a383dd5104a5ff1" integrity sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ== +xregexp@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" + integrity sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA== + xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -8764,10 +9727,10 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yallist@^4.0.0: version "4.0.0" @@ -8800,6 +9763,11 @@ yargs-parser@^20.2.2, yargs-parser@^20.2.3: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + yargs-unparser@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" @@ -8856,17 +9824,17 @@ yargs@^16.1.0, yargs@^16.2.0: yargs-parser "^20.2.2" yargs@^17.0.0: - version "17.2.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.2.1.tgz#e2c95b9796a0e1f7f3bf4427863b42e0418191ea" - integrity sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q== + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: - cliui "^7.0.2" + cliui "^8.0.1" escalade "^3.1.1" get-caller-file "^2.0.5" require-directory "^2.1.1" - string-width "^4.2.0" + string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^20.2.2" + yargs-parser "^21.1.1" yn@3.1.1: version "3.1.1"