mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
Compare commits
24 Commits
d8444fc3ed
...
974803ce41
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
974803ce41 | ||
|
|
14e2ae3eb9 | ||
|
|
ffd735dfdd | ||
|
|
2133c97437 | ||
|
|
ef9e4b6f8e | ||
|
|
cc07c90f1d | ||
|
|
544f640db0 | ||
|
|
a46eb0a7e1 | ||
|
|
200d3df91d | ||
|
|
2d8c5158db | ||
|
|
6e34756b9d | ||
|
|
73fda419e4 | ||
|
|
6f486e5a67 | ||
|
|
38715bbd41 | ||
|
|
ec3ea10b44 | ||
|
|
c4f5d12f3f | ||
|
|
61f9e0d085 | ||
|
|
55cd8e2b08 | ||
|
|
67f793feaa | ||
|
|
835647ac92 | ||
|
|
546192767d | ||
|
|
d0b54544e9 | ||
|
|
cfb3d6c015 | ||
|
|
dd55218648 |
@ -1,7 +1,7 @@
|
||||
{
|
||||
"all": true,
|
||||
"cache": false,
|
||||
"exclude": ["node_modules", "**/*.d.ts"],
|
||||
"exclude": ["**/*.d.ts"],
|
||||
"exclude-after-remap": true,
|
||||
"extension": [".ts"],
|
||||
"include": ["build/compiled/src/**", "src/**"],
|
||||
|
||||
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -33,8 +33,8 @@
|
||||
|
||||
- [ ] Code is up-to-date with the `master` branch
|
||||
- [ ] This pull request links relevant issues as `Fixes #00000`
|
||||
- [ ] There are new or updated unit tests validating the change
|
||||
- [ ] Documentation has been updated to reflect this change
|
||||
- [ ] There are new or updated tests validating the change (`tests/**.test.ts`)
|
||||
- [ ] Documentation has been updated to reflect this change (`docs/docs/**.md`)
|
||||
|
||||
<!--
|
||||
🎉 Thank you for contributing and making TypeORM even better!
|
||||
|
||||
28
.github/workflows/docsearch.yml
vendored
28
.github/workflows/docsearch.yml
vendored
@ -12,7 +12,35 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Delete unaliased collections
|
||||
env:
|
||||
TYPESENSE_API_KEY: ${{ secrets.TYPESENSE_API_KEY }}
|
||||
TYPESENSE_HOST: ${{ secrets.TYPESENSE_HOST }}
|
||||
TYPESENSE_PROTOCOL: https
|
||||
TYPESENSE_PORT: 443
|
||||
run: |
|
||||
ALIAS_COLLECTION=$(curl -s -H "X-TYPESENSE-API-KEY: $TYPESENSE_API_KEY" \
|
||||
"$TYPESENSE_PROTOCOL://$TYPESENSE_HOST:$TYPESENSE_PORT/aliases/typeorm-docs" \
|
||||
| jq -r '.collection_name')
|
||||
|
||||
if [ "$ALIAS_COLLECTION" = "null" ] || [ -z "$ALIAS_COLLECTION" ]; then
|
||||
echo "Alias does not exist; skipping collection cleanup."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Alias currently points to: $ALIAS_COLLECTION"
|
||||
|
||||
COLLECTIONS=$(curl -s -H "X-TYPESENSE-API-KEY: $TYPESENSE_API_KEY" \
|
||||
"$TYPESENSE_PROTOCOL://$TYPESENSE_HOST:$TYPESENSE_PORT/collections" \
|
||||
| jq -r '.[].name')
|
||||
|
||||
for col in $COLLECTIONS; do
|
||||
if [ "$col" != "$ALIAS_COLLECTION" ]; then
|
||||
echo "Deleting unaliased collection: $col"
|
||||
curl -s -X DELETE -H "X-TYPESENSE-API-KEY: $TYPESENSE_API_KEY" \
|
||||
"$TYPESENSE_PROTOCOL://$TYPESENSE_HOST:$TYPESENSE_PORT/collections/$col"
|
||||
fi
|
||||
done
|
||||
- run: |
|
||||
docker run \
|
||||
-e TYPESENSE_API_KEY=${{ secrets.TYPESENSE_API_KEY }} \
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
"skip": false,
|
||||
"name": "mysql",
|
||||
"type": "mysql",
|
||||
"connectorPackage": "mysql2",
|
||||
"host": "localhost",
|
||||
"port": 3306,
|
||||
"username": "root",
|
||||
@ -16,7 +15,6 @@
|
||||
"skip": false,
|
||||
"name": "mariadb",
|
||||
"type": "mariadb",
|
||||
"connectorPackage": "mysql2",
|
||||
"host": "localhost",
|
||||
"port": 3307,
|
||||
"username": "root",
|
||||
|
||||
17
.github/workflows/tests.yml
vendored
17
.github/workflows/tests.yml
vendored
@ -34,6 +34,7 @@ jobs:
|
||||
|
||||
src-or-tests: &src-or-tests
|
||||
- *src
|
||||
- test/**/*.ts
|
||||
- .github/workflows/test/**/*
|
||||
- .github/workflows/test*.yml
|
||||
- .mocharc.json
|
||||
@ -58,6 +59,21 @@ jobs:
|
||||
- run: npm run lint
|
||||
- run: npm run format:ci
|
||||
|
||||
lock-file:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: .nvmrc
|
||||
- run: npm install
|
||||
- run: git status
|
||||
- run: |
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo "package-lock.json is not up to date or was generated with a different npm version than the one shipped with Node.js $(cat .nvmrc)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docs:
|
||||
if: contains(needs.detect-changes.outputs.changes, 'docs')
|
||||
needs: detect-changes
|
||||
@ -125,6 +141,7 @@ jobs:
|
||||
- coverage
|
||||
- docs
|
||||
- formatting
|
||||
- lock-file
|
||||
- tests-linux
|
||||
- tests-windows
|
||||
steps:
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
{
|
||||
"__comment": "TODO: remove --exit flag: https://mochajs.org/#-exit",
|
||||
"exit": true,
|
||||
"$schema": "https://json.schemastore.org/mocharc",
|
||||
"check-leaks": true,
|
||||
"color": true,
|
||||
"exit": true,
|
||||
"file": ["./build/compiled/test/utils/test-setup.js"],
|
||||
"recursive": true,
|
||||
"spec": ["./build/compiled/test"],
|
||||
"spec": ["./build/compiled/test/**/*.test.{js,ts}"],
|
||||
"timeout": 90000
|
||||
}
|
||||
|
||||
28
CHANGELOG.md
28
CHANGELOG.md
@ -1,3 +1,31 @@
|
||||
## [0.3.28](https://github.com/typeorm/typeorm/compare/0.3.27...0.3.28) (2025-12-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add multiSubnetFailover option for mssql ([#10804](https://github.com/typeorm/typeorm/issues/10804)) ([83e3a8a](https://github.com/typeorm/typeorm/commit/83e3a8a3db581a50495fa2d97c8fcd5d603cfd3c))
|
||||
* circular import in SapDriver.ts ([#11750](https://github.com/typeorm/typeorm/issues/11750)) ([bed7913](https://github.com/typeorm/typeorm/commit/bed79136230d4ab26cce8cf79071134c75527857))
|
||||
* **cli:** init command reading package.json from two folders up ([#11789](https://github.com/typeorm/typeorm/issues/11789)) ([dd55218](https://github.com/typeorm/typeorm/commit/dd55218648eb449937e22e1e7c88182db0048f1d))
|
||||
* **deps:** upgrade glob to fix CVE-2025-64756 ([#11784](https://github.com/typeorm/typeorm/issues/11784)) ([dc74f53](https://github.com/typeorm/typeorm/commit/dc74f5374ef5ec83d53045e4bca99cb9ff7d49d4))
|
||||
* **mongodb:** add missing `findBy` method to MongoEntityManager ([#11814](https://github.com/typeorm/typeorm/issues/11814)) ([38715bb](https://github.com/typeorm/typeorm/commit/38715bbd4169cae2910aac035cd2b05bddbaec5c))
|
||||
* **redis:** version detection logic ([#11815](https://github.com/typeorm/typeorm/issues/11815)) ([6f486e5](https://github.com/typeorm/typeorm/commit/6f486e5a67c007287949be119f233fb2b4fb7a59))
|
||||
* typesense doc sync ([#11807](https://github.com/typeorm/typeorm/issues/11807)) ([d0b5454](https://github.com/typeorm/typeorm/commit/d0b54544e9e43a5330c0485d41551128224fe4d3))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support for `jsonpath` column type in PostgreSQL ([#11684](https://github.com/typeorm/typeorm/issues/11684)) ([4f05718](https://github.com/typeorm/typeorm/commit/4f05718237a6ef1a3bc623e803536db23f1f327b))
|
||||
* **cli/init:** pick dependencies versions from our own package.json ([#11705](https://github.com/typeorm/typeorm/issues/11705)) ([b930909](https://github.com/typeorm/typeorm/commit/b9309098bc00de047a96cba642ea1ed9e730b1fa))
|
||||
* entity schema support trees ([#11606](https://github.com/typeorm/typeorm/issues/11606)) ([925dee0](https://github.com/typeorm/typeorm/commit/925dee002b92f1210456dce16c18c6b436e912f3))
|
||||
* export QueryPartialEntity and QueryDeepPartialEntity types ([#11748](https://github.com/typeorm/typeorm/issues/11748)) ([ade198c](https://github.com/typeorm/typeorm/commit/ade198c77cda65e86f057f97261073f5ab2b1ed6))
|
||||
* init version in postgres driver only if not set ([#11373](https://github.com/typeorm/typeorm/issues/11373)) ([cb1284c](https://github.com/typeorm/typeorm/commit/cb1284c8c0950dcb792e95b889efe1dfafc05aea))
|
||||
* manage MongoDB SOCKS5 proxy settings ([#11731](https://github.com/typeorm/typeorm/issues/11731)) ([d7867eb](https://github.com/typeorm/typeorm/commit/d7867ebff173e6cae45e6ce82c9f8890811c4eba))
|
||||
* **mssql:** support 'vector' type for MS SQL Server ([#11732](https://github.com/typeorm/typeorm/issues/11732)) ([2681051](https://github.com/typeorm/typeorm/commit/2681051f78c5c284b340e7978f8f337e86c7e915))
|
||||
* **mysql:** add pool size options for each connection ([#11810](https://github.com/typeorm/typeorm/issues/11810)) ([67f793f](https://github.com/typeorm/typeorm/commit/67f793feaa976da717175daf152f738793b94ed2))
|
||||
* **mysql:** add support for vector columns on MariaDB and MySQL ([#11670](https://github.com/typeorm/typeorm/issues/11670)) ([cfb3d6c](https://github.com/typeorm/typeorm/commit/cfb3d6c015ad648a7ffc08a7a11ce580d108ac69))
|
||||
|
||||
|
||||
|
||||
## [0.3.27](https://github.com/typeorm/typeorm/compare/0.3.26...0.3.27) (2025-09-19)
|
||||
|
||||
|
||||
|
||||
37
DEVELOPER.md
37
DEVELOPER.md
@ -2,11 +2,11 @@
|
||||
|
||||
This document describes how to set up your development environment and run TypeORM test cases.
|
||||
|
||||
- [Prerequisite Software](#prerequisite-software)
|
||||
- [Getting the Sources](#getting-the-sources)
|
||||
- [Installing NPM Modules](#installing-npm-modules)
|
||||
- [Building](#building)
|
||||
- [Running Tests Locally](#running-tests-locally)
|
||||
* [Prerequisite Software](#prerequisite-software)
|
||||
* [Getting the Sources](#getting-the-sources)
|
||||
* [Installing NPM Modules](#installing-npm-modules)
|
||||
* [Building](#building)
|
||||
* [Running Tests Locally](#running-tests-locally)
|
||||
|
||||
See the [contribution guidelines](https://github.com/typeorm/typeorm/blob/master/CONTRIBUTING.md)
|
||||
if you'd like to contribute to TypeORM.
|
||||
@ -16,14 +16,14 @@ if you'd like to contribute to TypeORM.
|
||||
Before you can build and test TypeORM, you must install and configure the
|
||||
following products on your development machine:
|
||||
|
||||
- [Git](http://git-scm.com) and/or the **GitHub app** (for [Mac](http://mac.github.com) or [Windows](http://windows.github.com));
|
||||
* [Git](http://git-scm.com) and/or the **GitHub app** (for [Mac](http://mac.github.com) or [Windows](http://windows.github.com));
|
||||
[GitHub's Guide to Installing Git](https://docs.github.com/get-started/git-basics/set-up-git) is a good source of information.
|
||||
- [Node.js](https://nodejs.org) can be installed from the official website, the operating system's package manager, or using a Node.js version manager like [fnm](https://fnm.vercel.app) or [nvm](https://github.com/nvm-sh/nvm).
|
||||
- [Mysql](https://www.mysql.com/) is required to run tests on this platform (or docker)
|
||||
- [MariaDB](https://mariadb.com/) is required to run tests on this platform (or docker)
|
||||
- [Postgres](https://www.postgresql.org/) is required to run tests on this platform (or docker)
|
||||
- [Oracle](https://www.oracle.com/database/index.html) is required to run tests on this platform
|
||||
- [Microsoft SQL Server](https://www.microsoft.com/en-us/cloud-platform/sql-server) is required to run tests on this platform
|
||||
* [Node.js](https://nodejs.org) can be installed from the official website, the operating system's package manager, or using a Node.js version manager like [fnm](https://fnm.vercel.app).
|
||||
* [MySQL](https://www.mysql.com/) is required to run tests on this platform (or docker)
|
||||
* [MariaDB](https://mariadb.com/) is required to run tests on this platform (or docker)
|
||||
* [Postgres](https://www.postgresql.org/) is required to run tests on this platform (or docker)
|
||||
* [Oracle](https://www.oracle.com/database/index.html) is required to run tests on this platform
|
||||
* [Microsoft SQL Server](https://www.microsoft.com/en-us/cloud-platform/sql-server) is required to run tests on this platform
|
||||
|
||||
For convenience, you can also use the [Docker](https://www.docker.com/) images
|
||||
provided in [docker-compose.yml](https://github.com/typeorm/typeorm/blob/master/docker-compose.yml)
|
||||
@ -59,9 +59,9 @@ You should have node installed in the version described in [.nvmrc](.nvmrc).
|
||||
|
||||
It is recommended to configure your OS to automatically switch to use this version whenever you enter project folder. This can be achieved in many ways:
|
||||
|
||||
* [`fnm`](https://github.com/Schniz/fnm)
|
||||
* [`zsh-nvm`](https://github.com/lukechilds/zsh-nvm#auto-use)
|
||||
* [`asdf`](https://asdf-vm.com) with `asdf-nodejs` plugin and [`legacy_version_file = true`](https://asdf-vm.com/manage/configuration.html#legacy-version-file) option
|
||||
- [`fnm`](https://github.com/Schniz/fnm)
|
||||
- [`zsh-nvm`](https://github.com/lukechilds/zsh-nvm#auto-use)
|
||||
- [`asdf`](https://asdf-vm.com) with `asdf-nodejs` plugin and [`legacy_version_file = true`](https://asdf-vm.com/manage/configuration.html#legacy-version-file) option
|
||||
|
||||
## Installing package dependencies
|
||||
|
||||
@ -104,7 +104,7 @@ You can copy this tar into your project and run `npm install ./typeorm-x.x.x.tgz
|
||||
|
||||
It is greatly appreciated if PRs that change code come with appropriate tests.
|
||||
|
||||
To create a new test, check the [relevant functional tests](https://github.com/typeorm/typeorm/tree/master/test/functional). Depending on the test, you may need to create a new test file or modify an existing one.
|
||||
To create a new test, check the [relevant functional tests](https://github.com/typeorm/typeorm/tree/master/test/functional). Depending on the test, you may need to create a new `.test.ts` file or modify an existing one.
|
||||
|
||||
If the test is for a specific regression or issue opened on GitHub, add a comment to the tests mentioning the issue number.
|
||||
|
||||
@ -116,11 +116,12 @@ import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
} from "../../../utils/test-utils"
|
||||
import { DataSource } from "../../../../src/data-source/DataSource"
|
||||
} from "../../utils/test-utils"
|
||||
import { DataSource } from "../../../src/data-source/DataSource"
|
||||
|
||||
describe("description of the functionality you're testing", () => {
|
||||
let dataSources: DataSource[]
|
||||
|
||||
before(
|
||||
async () =>
|
||||
(dataSources = await createTestingConnections({
|
||||
|
||||
@ -12,7 +12,7 @@ services:
|
||||
MYSQL_DATABASE: "test"
|
||||
|
||||
mysql-9:
|
||||
image: "mysql:9.4.0"
|
||||
image: "mysql:9.5.0"
|
||||
container_name: "typeorm-mysql-9"
|
||||
ports:
|
||||
- "3306:3306"
|
||||
@ -24,7 +24,7 @@ services:
|
||||
|
||||
# mariadb
|
||||
mariadb-10:
|
||||
image: "mariadb:10.6.22-jammy"
|
||||
image: "mariadb:10.6.24-jammy"
|
||||
container_name: "typeorm-mariadb-10"
|
||||
ports:
|
||||
- "3307:3306"
|
||||
@ -35,7 +35,7 @@ services:
|
||||
MYSQL_DATABASE: "test"
|
||||
|
||||
mariadb-12:
|
||||
image: "mariadb:12.0.1-rc"
|
||||
image: "mariadb:12.1.2"
|
||||
container_name: "typeorm-mariadb-12"
|
||||
ports:
|
||||
- "3307:3306"
|
||||
|
||||
@ -207,7 +207,7 @@ const queryEmbedding = [
|
||||
const results = await dataSource.query(
|
||||
`
|
||||
DECLARE @question AS VECTOR (1998) = @0;
|
||||
SELECT TOP (10) dc.*,
|
||||
SELECT TOP (10) dc.*,
|
||||
VECTOR_DISTANCE('cosine', @question, embedding) AS distance
|
||||
FROM document_chunk dc
|
||||
ORDER BY VECTOR_DISTANCE('cosine', @question, embedding)
|
||||
|
||||
@ -4,14 +4,6 @@ MySQL, MariaDB and Amazon Aurora MySQL are supported as TypeORM drivers.
|
||||
|
||||
## Installation
|
||||
|
||||
Either `mysql` or `mysql2` are required to connect to a MySQL/MariaDB data source. Only `mysql2` can connect to MySQL 8.0 or later and is recommended because it is still maintained. See more about [mysql2](https://sidorares.github.io/node-mysql2/docs/history-and-why-mysq2).
|
||||
|
||||
```shell
|
||||
npm install mysql
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```shell
|
||||
npm install mysql2
|
||||
```
|
||||
@ -20,8 +12,6 @@ npm install mysql2
|
||||
|
||||
See [Data Source Options](../data-source/2-data-source-options.md) for the common data source options. You can use the data source types `mysql`, `mariadb` and `aurora-mysql` to connect to the respective databases.
|
||||
|
||||
- `connectorPackage` - The database client, either `mysql` or `mysql2`. If the specified client cannot be loaded, it will fall back to the alternative. (Current default: `mysql`)
|
||||
|
||||
- `url` - Connection url where the connection is performed. Please note that other data source options will override parameters set from url.
|
||||
|
||||
- `host` - Database host.
|
||||
@ -34,6 +24,10 @@ See [Data Source Options](../data-source/2-data-source-options.md) for the commo
|
||||
|
||||
- `database` - Database name.
|
||||
|
||||
- `socketPath` - Database socket path.
|
||||
|
||||
- `poolSize` - Maximum number of clients the pool should contain for each connection.
|
||||
|
||||
- `charset` and `collation` - The charset/collation for the connection. If an SQL-level charset is specified (like utf8mb4) then the default collation for that charset is used.
|
||||
|
||||
- `timezone` - the timezone configured on the MySQL server. This is used to typecast server date/time
|
||||
@ -82,7 +76,7 @@ See [Data Source Options](../data-source/2-data-source-options.md) for the commo
|
||||
|
||||
- `enableQueryTimeout` - If a value is specified for maxQueryExecutionTime, in addition to generating a warning log when a query exceeds this time limit, the specified maxQueryExecutionTime value is also used as the timeout for the query. For more information, check [mysql timeouts](https://github.com/mysqljs/mysql#timeouts).
|
||||
|
||||
Additional options can be added to the `extra` object and will be passed directly to the client library. See more in the [mysql connection options](https://github.com/mysqljs/mysql#connection-options) or the [mysql2 documentation](https://sidorares.github.io/node-mysql2/docs).
|
||||
Additional options can be added to the `extra` object and will be passed directly to the client library. See more in the [mysql2 documentation](https://sidorares.github.io/node-mysql2/docs).
|
||||
|
||||
## Column Types
|
||||
|
||||
@ -139,3 +133,7 @@ export class User {
|
||||
roles: UserRoleType[]
|
||||
}
|
||||
```
|
||||
|
||||
### Vector Types
|
||||
|
||||
MySQL supports the [VECTOR type](https://dev.mysql.com/doc/refman/en/vector.html) since version 9.0, while in MariaDB, [vectors](https://mariadb.com/docs/server/reference/sql-structure/vectors/vector-overview) are available since 11.7.
|
||||
|
||||
@ -60,7 +60,7 @@ Additional options can be added to the `extra` object and will be passed directl
|
||||
|
||||
### Column types for `postgres`
|
||||
|
||||
`int`, `int2`, `int4`, `int8`, `smallint`, `integer`, `bigint`, `decimal`, `numeric`, `real`, `float`, `float4`, `float8`, `double precision`, `money`, `character varying`, `varchar`, `character`, `char`, `text`, `citext`, `hstore`, `bytea`, `bit`, `varbit`, `bit varying`, `timetz`, `timestamptz`, `timestamp`, `timestamp without time zone`, `timestamp with time zone`, `date`, `time`, `time without time zone`, `time with time zone`, `interval`, `bool`, `boolean`, `enum`, `point`, `line`, `lseg`, `box`, `path`, `polygon`, `circle`, `cidr`, `inet`, `macaddr`, `macaddr8`, `tsvector`, `tsquery`, `uuid`, `xml`, `json`, `jsonb`, `jsonpath`, `int4range`, `int8range`, `numrange`, `tsrange`, `tstzrange`, `daterange`, `int4multirange`, `int8multirange`, `nummultirange`, `tsmultirange`, `tstzmultirange`, `multidaterange`, `geometry`, `geography`, `cube`, `ltree`
|
||||
`int`, `int2`, `int4`, `int8`, `smallint`, `integer`, `bigint`, `decimal`, `numeric`, `real`, `float`, `float4`, `float8`, `double precision`, `money`, `character varying`, `varchar`, `character`, `char`, `text`, `citext`, `hstore`, `bytea`, `bit`, `varbit`, `bit varying`, `timetz`, `timestamptz`, `timestamp`, `timestamp without time zone`, `timestamp with time zone`, `date`, `time`, `time without time zone`, `time with time zone`, `interval`, `bool`, `boolean`, `enum`, `point`, `line`, `lseg`, `box`, `path`, `polygon`, `circle`, `cidr`, `inet`, `macaddr`, `macaddr8`, `tsvector`, `tsquery`, `uuid`, `xml`, `json`, `jsonb`, `jsonpath`, `int4range`, `int8range`, `numrange`, `tsrange`, `tstzrange`, `daterange`, `int4multirange`, `int8multirange`, `nummultirange`, `tsmultirange`, `tstzmultirange`, `multidaterange`, `geometry`, `geography`, `cube`, `ltree`, `vector`, `halfvec`.
|
||||
|
||||
### Column types for `cockroachdb`
|
||||
|
||||
@ -68,6 +68,33 @@ Additional options can be added to the `extra` object and will be passed directl
|
||||
|
||||
Note: CockroachDB returns all numeric data types as `string`. However, if you omit the column type and define your property as `number` ORM will `parseInt` string into number.
|
||||
|
||||
### Vector columns
|
||||
|
||||
Vector columns can be used for similarity searches using PostgreSQL's vector operators:
|
||||
|
||||
```typescript
|
||||
// L2 distance (Euclidean) - <->
|
||||
const results = await dataSource.sql`
|
||||
SELECT id, embedding
|
||||
FROM post
|
||||
ORDER BY embedding <-> ${"[1,2,3]"}
|
||||
LIMIT 5`
|
||||
|
||||
// Cosine distance - <=>
|
||||
const results = await dataSource.sql`
|
||||
SELECT id, embedding
|
||||
FROM post
|
||||
ORDER BY embedding <=> ${"[1,2,3]"}
|
||||
LIMIT 5`
|
||||
|
||||
// Inner product - <#>
|
||||
const results = await dataSource.sql`
|
||||
SELECT id, embedding
|
||||
FROM post
|
||||
ORDER BY embedding <#> ${"[1,2,3]"}
|
||||
LIMIT 5`
|
||||
```
|
||||
|
||||
### Spatial columns
|
||||
|
||||
TypeORM's PostgreSQL and CockroachDB support uses [GeoJSON](http://geojson.org/) as an interchange format, so geometry columns should be tagged either as `object` or `Geometry` (or subclasses, e.g. `Point`) after importing [`geojson` types](https://www.npmjs.com/package/@types/geojson) or using the TypeORM built-in GeoJSON types:
|
||||
|
||||
@ -37,15 +37,16 @@ SAP HANA 2.0 and SAP HANA Cloud support slightly different data types. Check the
|
||||
- [SAP HANA 2.0 Data Types](https://help.sap.com/docs/SAP_HANA_PLATFORM/4fe29514fd584807ac9f2a04f6754767/20a1569875191014b507cf392724b7eb.html?locale=en-US)
|
||||
- [SAP HANA Cloud Data Types](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/data-types)
|
||||
|
||||
TypeORM's `SapDriver` supports `tinyint`, `smallint`, `integer`, `bigint`, `smalldecimal`, `decimal`, `real`, `double`, `date`, `time`, `seconddate`, `timestamp`, `boolean`, `char`, `nchar`, `varchar`, `nvarchar`, `text`, `alphanum`, `shorttext`, `array`, `varbinary`, `blob`, `clob`, `nclob`, `st_geometry`, `st_point`, `real_vector`, `half_vector`, `vector`, and `halfvec`. Some of these data types have been deprecated or removed in SAP HANA Cloud, and will be converted to the closest available alternative when connected to a Cloud database.
|
||||
TypeORM's `SapDriver` supports `tinyint`, `smallint`, `integer`, `bigint`, `smalldecimal`, `decimal`, `real`, `double`, `date`, `time`, `seconddate`, `timestamp`, `boolean`, `char`, `nchar`, `varchar`, `nvarchar`, `text`, `alphanum`, `shorttext`, `array`, `varbinary`, `blob`, `clob`, `nclob`, `st_geometry`, `st_point`, `real_vector` and `half_vector`. Some of these data types have been deprecated or removed in SAP HANA Cloud, and will be converted to the closest available alternative when connected to a Cloud database.
|
||||
|
||||
### Vector Types
|
||||
|
||||
The `real_vector` and `half_vector` data types were introduced in SAP HANA Cloud (2024Q1 and 2025Q2 respectively), and require a supported version of `@sap/hana-client` as well.
|
||||
The `real_vector` and `half_vector` data types were introduced in SAP HANA Cloud (2024Q1 and 2025Q2 respectively), and require a supported version of `@sap/hana-client` as well.
|
||||
|
||||
For consistency with PostgreSQL's vector support, TypeORM also provides aliases:
|
||||
- `vector` (alias for `real_vector`) - stores vectors as 4-byte floats
|
||||
- `halfvec` (alias for `half_vector`) - stores vectors as 2-byte floats for memory efficiency
|
||||
|
||||
- `vector` (alias for `real_vector`) - stores vectors as 4-byte floats
|
||||
- `halfvec` (alias for `half_vector`) - stores vectors as 2-byte floats for memory efficiency
|
||||
|
||||
```typescript
|
||||
@Entity()
|
||||
@ -70,3 +71,5 @@ export class Document {
|
||||
```
|
||||
|
||||
By default, the client will return a `Buffer` in the `fvecs`/`hvecs` format, which is more efficient. It is possible to let the driver convert the values to a `number[]` by adding `{ extra: { vectorOutputType: "Array" } }` to the connection options. Check the SAP HANA Client documentation for more information about [REAL_VECTOR](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/0d197e4389c64e6b9cf90f6f698f62fe.html) or [HALF_VECTOR](https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/8bb854b4ce4a4299bed27c365b717e91.html).
|
||||
|
||||
Use the appropriate [vector functions](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/vector-functions) for similarity searches.
|
||||
|
||||
@ -180,88 +180,6 @@ There are several special column types with additional functionality available:
|
||||
each time you call `save` of entity manager or repository, or during `upsert` operations when an update occurs.
|
||||
You don't need to set this column - it will be automatically set.
|
||||
|
||||
### Vector columns
|
||||
|
||||
Vector columns are supported on PostgreSQL (via [`pgvector`](https://github.com/pgvector/pgvector) extension), Microsoft SQL Server, and SAP HANA Cloud, enabling storing and querying vector embeddings for similarity search and machine learning applications.
|
||||
|
||||
TypeORM supports both `vector` and `halfvec` column types across databases:
|
||||
|
||||
- `vector` - stores vectors as 4-byte floats (single precision)
|
||||
- PostgreSQL: native `vector` type via pgvector extension
|
||||
- SQL Server: native `vector` type
|
||||
- SAP HANA: alias for `real_vector` type
|
||||
- `halfvec` - stores vectors as 2-byte floats (half precision) for memory efficiency
|
||||
- PostgreSQL: native `halfvec` type via pgvector extension
|
||||
- SAP HANA: alias for `half_vector` type
|
||||
|
||||
You can specify the vector dimensions using the `length` option:
|
||||
|
||||
```typescript
|
||||
@Entity()
|
||||
export class Post {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
// Vector without specified dimensions (works on PostgreSQL and SAP HANA; SQL Server requires explicit dimensions)
|
||||
@Column("vector")
|
||||
embedding: number[] | Buffer
|
||||
|
||||
// Vector with 3 dimensions: vector(3)
|
||||
@Column("vector", { length: 3 })
|
||||
embedding_3d: number[] | Buffer
|
||||
|
||||
// Half-precision vector with 4 dimensions: halfvec(4) (PostgreSQL and SAP HANA only)
|
||||
@Column("halfvec", { length: 4 })
|
||||
halfvec_embedding: number[] | Buffer
|
||||
}
|
||||
```
|
||||
|
||||
**PostgreSQL** - Vector columns can be used for similarity searches using vector operators:
|
||||
|
||||
```typescript
|
||||
// L2 distance (Euclidean) - <->
|
||||
const results = await dataSource.query(
|
||||
`SELECT id, embedding FROM post ORDER BY embedding <-> $1 LIMIT 5`,
|
||||
["[1,2,3]"],
|
||||
)
|
||||
|
||||
// Cosine distance - <=>
|
||||
const results = await dataSource.query(
|
||||
`SELECT id, embedding FROM post ORDER BY embedding <=> $1 LIMIT 5`,
|
||||
["[1,2,3]"],
|
||||
)
|
||||
|
||||
// Inner product - <#>
|
||||
const results = await dataSource.query(
|
||||
`SELECT id, embedding FROM post ORDER BY embedding <#> $1 LIMIT 5`,
|
||||
["[1,2,3]"],
|
||||
)
|
||||
```
|
||||
|
||||
**SQL Server** - Use the `VECTOR_DISTANCE` function for similarity searches:
|
||||
|
||||
```typescript
|
||||
const queryEmbedding = [1, 2, 3]
|
||||
|
||||
// Cosine distance
|
||||
const results = await dataSource.query(
|
||||
`
|
||||
DECLARE @question AS VECTOR(3) = @0;
|
||||
SELECT TOP (5) id, embedding,
|
||||
VECTOR_DISTANCE('cosine', @question, embedding) AS distance
|
||||
FROM post
|
||||
ORDER BY VECTOR_DISTANCE('cosine', @question, embedding)
|
||||
`,
|
||||
[JSON.stringify(queryEmbedding)],
|
||||
)
|
||||
```
|
||||
|
||||
> **Note**:
|
||||
>
|
||||
> - **PostgreSQL**: Vector columns require the `pgvector` extension to be installed. The extension provides the vector data types and similarity operators.
|
||||
> - **SQL Server**: Vector type support requires a compatible SQL Server version with vector functionality enabled.
|
||||
> - **SAP HANA**: Vector columns require SAP HANA Cloud (2024Q1+) and a supported version of `@sap/hana-client`. Use the appropriate [vector similarity functions](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-sql-reference-guide/vector-functions) for similarity searches.
|
||||
|
||||
## Column types
|
||||
|
||||
TypeORM supports all of the most commonly used database-supported column types.
|
||||
@ -414,6 +332,50 @@ Besides "uuid" there is also "increment", "identity" (Postgres 10+ only) and "ro
|
||||
on some database platforms with this type of generation (for example some databases can only have one increment column,
|
||||
or some of them require increment to be a primary key).
|
||||
|
||||
### Vector columns
|
||||
|
||||
Vector columns are supported on MariaDB/MySQL, Microsoft SQL Server, PostgreSQL (via [`pgvector`](https://github.com/pgvector/pgvector) extension) and SAP HANA Cloud, enabling storing and querying vector embeddings for similarity search and machine learning applications.
|
||||
|
||||
TypeORM supports both `vector` and `halfvec` column types across databases:
|
||||
|
||||
- `vector` - stores vectors as 4-byte floats (single precision)
|
||||
- MariaDB/MySQL: native `vector` type
|
||||
- Microsoft SQL Server: native `vector` type
|
||||
- PostgreSQL: `vector` type, available via `pgvector` extension
|
||||
- SAP HANA Cloud: alias for `real_vector` type
|
||||
- `halfvec` - stores vectors as 2-byte floats (half precision) for memory efficiency
|
||||
- PostgreSQL: `halfvec` type, available via `pgvector` extension
|
||||
- SAP HANA Cloud: alias for `half_vector` type
|
||||
|
||||
You can specify the number of vector dimensions using the `length` option:
|
||||
|
||||
```typescript
|
||||
@Entity()
|
||||
export class Post {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
// Vector without specified dimensions
|
||||
@Column("vector")
|
||||
embedding: number[] | Buffer
|
||||
|
||||
// Vector with 3 dimensions: vector(3)
|
||||
@Column("vector", { length: 3 })
|
||||
embedding_3d: number[] | Buffer
|
||||
|
||||
// Half-precision vector with 4 dimensions: halfvec(4) (works on PostgreSQL and SAP HANA only)
|
||||
@Column("halfvec", { length: 4 })
|
||||
halfvec_embedding: number[] | Buffer
|
||||
}
|
||||
```
|
||||
|
||||
> **Note**:
|
||||
>
|
||||
> - **MariaDB/MySQL**: Vectors are supported since MariaDB 11.7 and MySQL 9
|
||||
> - **Microsoft SQL Server**: Vector type support requires SQL Server 2025 (17.x) or newer.
|
||||
> - **PostgreSQL**: Vector columns require the `pgvector` extension to be installed. The extension provides the vector data types and similarity operators.
|
||||
> - **SAP HANA**: Vector columns require SAP HANA Cloud (2024Q1+) and a supported version of `@sap/hana-client`.
|
||||
|
||||
### Spatial columns
|
||||
|
||||
Microsoft SQLServer, MySQL/MariaDB, PostgreSQL/CockroachDB and SAP HANA all support spatial columns. TypeORM's support for each varies slightly between databases, particularly as the column names vary between databases.
|
||||
@ -491,6 +453,7 @@ List of available options in `ColumnOptions`:
|
||||
- `hstoreType: "object"|"string"` - Return type of `HSTORE` column. Returns value as string or as object. Used only in [Postgres](https://www.postgresql.org/docs/9.6/static/hstore.html).
|
||||
- `array: boolean` - Used for postgres and cockroachdb column types which can be array (for example int[])
|
||||
- `transformer: { from(value: DatabaseType): EntityType, to(value: EntityType): DatabaseType }` - Used to marshal properties of arbitrary type `EntityType` into a type `DatabaseType` supported by the database. Array of transformers are also supported and will be applied in natural order when writing, and in reverse order when reading. e.g. `[lowercase, encrypt]` will first lowercase the string then encrypt it when writing, and will decrypt then do nothing when reading.
|
||||
- `utc: boolean` - Indicates if date values should be stored and retrieved in UTC timezone instead of local timezone. Only applies to `date` column type. Default value is `false` (uses local timezone for backward compatibility).
|
||||
|
||||
Note: most of those column options are RDBMS-specific and aren't available in `MongoDB`.
|
||||
|
||||
|
||||
@ -170,7 +170,7 @@ module.exports = {
|
||||
plugins: [
|
||||
//ignore the drivers you don't want. This is the complete list of all drivers -- remove the suppressions for drivers you want to use.
|
||||
new FilterWarningsPlugin({
|
||||
exclude: [/mongodb/, /mssql/, /mysql/, /mysql2/, /oracledb/, /pg/, /pg-native/, /pg-query-stream/, /react-native-sqlite-storage/, /redis/, /sqlite3/, /sql.js/, /typeorm-aurora-data-api-driver/]
|
||||
exclude: [/mongodb/, /mssql/, /mysql2/, /oracledb/, /pg/, /pg-native/, /pg-query-stream/, /react-native-sqlite-storage/, /redis/, /sqlite3/, /sql.js/, /typeorm-aurora-data-api-driver/]
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
@ -27,12 +27,7 @@
|
||||
"strip_chars": " .,;:#",
|
||||
"custom_settings": {
|
||||
"separatorsToIndex": "_",
|
||||
"attributesForFaceting": [
|
||||
"language",
|
||||
"version",
|
||||
"type",
|
||||
"docusaurus_tag"
|
||||
],
|
||||
"attributesForFaceting": [],
|
||||
"attributesToRetrieve": [
|
||||
"hierarchy",
|
||||
"content",
|
||||
@ -46,4 +41,4 @@
|
||||
"833762294"
|
||||
],
|
||||
"nb_hits": 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { themes as prismThemes } from "prism-react-renderer"
|
||||
import type { Config } from "@docusaurus/types"
|
||||
import type * as Preset from "@docusaurus/preset-classic"
|
||||
import type { Config } from "@docusaurus/types"
|
||||
import { PluginOptions as LLMsTXTPluginOptions } from "@signalwire/docusaurus-plugin-llms-txt"
|
||||
import { themes as prismThemes } from "prism-react-renderer"
|
||||
import { redirects } from "./redirects"
|
||||
import { LLMsTXTPluginOptions } from "@signalwire/docusaurus-plugin-llms-txt"
|
||||
|
||||
// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)
|
||||
|
||||
@ -23,7 +23,6 @@ const config: Config = {
|
||||
projectName: "typeorm", // Usually your repo name.
|
||||
|
||||
onBrokenLinks: "throw",
|
||||
onBrokenMarkdownLinks: "warn",
|
||||
|
||||
// Even if you don't use internationalization, you can use this field to set
|
||||
// useful metadata like html lang. For example, if your site is Chinese, you
|
||||
|
||||
2447
docs/package-lock.json
generated
2447
docs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -27,24 +27,24 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.8.1",
|
||||
"@docusaurus/plugin-client-redirects": "^3.8.1",
|
||||
"@docusaurus/preset-classic": "3.8.1",
|
||||
"@docusaurus/core": "3.9.2",
|
||||
"@docusaurus/plugin-client-redirects": "^3.9.2",
|
||||
"@docusaurus/preset-classic": "3.9.2",
|
||||
"@mdx-js/react": "^3.1.1",
|
||||
"@signalwire/docusaurus-plugin-llms-txt": "^1.2.2",
|
||||
"clsx": "^2.1.1",
|
||||
"docusaurus-theme-search-typesense": "^0.25.0",
|
||||
"docusaurus-theme-search-typesense": "^0.26.0",
|
||||
"prism-react-renderer": "^2.4.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.8.1",
|
||||
"@docusaurus/tsconfig": "3.8.1",
|
||||
"@docusaurus/types": "3.8.1",
|
||||
"typescript": "~5.9.2"
|
||||
"@docusaurus/module-type-aliases": "3.9.2",
|
||||
"@docusaurus/tsconfig": "3.9.2",
|
||||
"@docusaurus/types": "3.9.2",
|
||||
"typescript": "~5.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0"
|
||||
"node": ">=20.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,10 +30,7 @@ export default defineConfig([
|
||||
js,
|
||||
ts,
|
||||
},
|
||||
extends: [
|
||||
js.configs.recommended,
|
||||
...ts.configs.recommendedTypeChecked,
|
||||
],
|
||||
extends: [js.configs.recommended, ...ts.configs.recommendedTypeChecked],
|
||||
rules: {
|
||||
// exceptions from typescript-eslint/recommended
|
||||
"@typescript-eslint/ban-ts-comment": "warn",
|
||||
@ -48,7 +45,7 @@ export default defineConfig([
|
||||
"warn",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
destructuredArrayIgnorePattern: "^_"
|
||||
destructuredArrayIgnorePattern: "^_",
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-wrapper-object-types": "off",
|
||||
@ -88,15 +85,14 @@ export default defineConfig([
|
||||
"no-regex-spaces": "warn",
|
||||
},
|
||||
},
|
||||
|
||||
jsdoc({
|
||||
files: ["src/**/*.ts"],
|
||||
config: "flat/recommended-typescript", // change to 'flat/recommended-typescript-error' once warnings are fixed
|
||||
// Temporarily enable individual rules when they are fixed, until all current warnings are gone,
|
||||
// and then remove manual config in favor of `config: "flat/recommended-typescript-error"`
|
||||
rules: {
|
||||
"jsdoc/valid-types": "error"
|
||||
}
|
||||
"jsdoc/valid-types": "error",
|
||||
},
|
||||
}),
|
||||
|
||||
{
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
"skip": false,
|
||||
"name": "mysql",
|
||||
"type": "mysql",
|
||||
"connectorPackage": "mysql2",
|
||||
"host": "localhost",
|
||||
"port": 3306,
|
||||
"username": "root",
|
||||
@ -16,7 +15,6 @@
|
||||
"skip": false,
|
||||
"name": "mariadb",
|
||||
"type": "mariadb",
|
||||
"connectorPackage": "mysql2",
|
||||
"host": "localhost",
|
||||
"port": 3307,
|
||||
"username": "root",
|
||||
|
||||
3674
package-lock.json
generated
3674
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
46
package.json
46
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "typeorm",
|
||||
"version": "0.3.27",
|
||||
"description": "Data-Mapper ORM for TypeScript and ES2023+. Supports MySQL/MariaDB, PostgreSQL, MS SQL Server, Oracle, SAP HANA, SQLite, MongoDB databases.",
|
||||
"version": "0.3.28",
|
||||
"description": "Data-Mapper ORM for TypeScript and ES2021+. Supports MySQL/MariaDB, PostgreSQL, MS SQL Server, Oracle, SAP HANA, SQLite, MongoDB databases.",
|
||||
"homepage": "https://typeorm.io",
|
||||
"bugs": {
|
||||
"url": "https://github.com/typeorm/typeorm/issues"
|
||||
@ -98,11 +98,10 @@
|
||||
"ansis": "^4.2.0",
|
||||
"app-root-path": "^3.1.0",
|
||||
"buffer": "^6.0.3",
|
||||
"dayjs": "^1.11.18",
|
||||
"dayjs": "^1.11.19",
|
||||
"debug": "^4.4.3",
|
||||
"dedent": "^1.7.0",
|
||||
"dotenv": "^17.2.3",
|
||||
"glob": "^10.5.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"sha.js": "^2.4.12",
|
||||
"sql-highlight": "^6.1.0",
|
||||
@ -113,13 +112,13 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.1",
|
||||
"@google-cloud/spanner": "^8.2.1",
|
||||
"@sap/hana-client": "^2.26.18",
|
||||
"@google-cloud/spanner": "^8.3.1",
|
||||
"@sap/hana-client": "^2.26.26",
|
||||
"@tsconfig/node20": "^20.1.6",
|
||||
"@types/chai": "^5.2.2",
|
||||
"@types/chai-as-promised": "^8.0.2",
|
||||
"@types/debug": "^4.1.12",
|
||||
"@types/gulp-rename": "^2.0.6",
|
||||
"@types/gulp-rename": "^2.0.7",
|
||||
"@types/gulp-sourcemaps": "^0.0.38",
|
||||
"@types/mocha": "^10.0.10",
|
||||
"@types/node": "^20.19.18",
|
||||
@ -127,7 +126,7 @@
|
||||
"@types/sinon": "^17.0.4",
|
||||
"@types/sinon-chai": "^4.0.0",
|
||||
"@types/source-map-support": "^0.5.10",
|
||||
"@types/yargs": "^17.0.33",
|
||||
"@types/yargs": "^17.0.35",
|
||||
"better-sqlite3": "^12.4.1",
|
||||
"c8": "^10.1.3",
|
||||
"chai": "^6.2.0",
|
||||
@ -135,7 +134,7 @@
|
||||
"class-transformer": "^0.5.1",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-chai-friendly": "^1.1.0",
|
||||
"eslint-plugin-jsdoc": "^61.1.12",
|
||||
"eslint-plugin-jsdoc": "^61.4.1",
|
||||
"globals": "^16.5.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-rename": "^2.1.0",
|
||||
@ -146,19 +145,17 @@
|
||||
"gulpclass": "^0.2.0",
|
||||
"husky": "^9.1.7",
|
||||
"is-ci": "^4.1.0",
|
||||
"lint-staged": "^16.2.6",
|
||||
"mocha": "^11.7.3",
|
||||
"mongodb": "^6.20.0",
|
||||
"mssql": "^12.0.0",
|
||||
"mysql": "^2.18.1",
|
||||
"mysql2": "^3.15.1",
|
||||
"oracledb": "^6.9.0",
|
||||
"lint-staged": "^16.2.7",
|
||||
"mocha": "^11.7.5",
|
||||
"mongodb": "^6.21.0",
|
||||
"mssql": "^12.1.1",
|
||||
"mysql2": "^3.15.3",
|
||||
"oracledb": "^6.10.0",
|
||||
"pg": "^8.16.3",
|
||||
"pg-query-stream": "^4.10.3",
|
||||
"pkg-pr-new": "^0.0.60",
|
||||
"prettier": "^3.6.2",
|
||||
"redis": "^5.8.2",
|
||||
"remap-istanbul": "^0.13.0",
|
||||
"redis": "^5.10.0",
|
||||
"sinon": "^21.0.0",
|
||||
"sinon-chai": "^4.0.1",
|
||||
"sort-package-json": "^3.4.0",
|
||||
@ -167,8 +164,8 @@
|
||||
"sqlite3": "^5.1.7",
|
||||
"standard-changelog": "^7.0.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.9.2",
|
||||
"typescript-eslint": "^8.46.3"
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.48.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@google-cloud/spanner": "^8.0.0",
|
||||
@ -177,7 +174,7 @@
|
||||
"ioredis": "^5.0.4",
|
||||
"mongodb": "^6.0.0",
|
||||
"mssql": "^12.0.0",
|
||||
"mysql2": "^3.0.1",
|
||||
"mysql2": "^3.15.3",
|
||||
"oracledb": "^6.3.0",
|
||||
"pg": "^8.5.1",
|
||||
"pg-native": "^3.0.0",
|
||||
@ -246,13 +243,6 @@
|
||||
"url": "https://opencollective.com/typeorm",
|
||||
"logo": "https://opencollective.com/opencollective/logo.txt"
|
||||
},
|
||||
"devEngines": {
|
||||
"packageManager": {
|
||||
"name": "npm",
|
||||
"onFail": "error"
|
||||
}
|
||||
},
|
||||
"readmeFilename": "README.md",
|
||||
"tags": [
|
||||
"orm",
|
||||
"typescript",
|
||||
|
||||
28
src/cache/RedisQueryResultCache.ts
vendored
28
src/cache/RedisQueryResultCache.ts
vendored
@ -300,26 +300,22 @@ export class RedisQueryResultCache implements QueryResultCache {
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects the Redis version based on the connected client's API characteristics
|
||||
* without creating test keys in the database
|
||||
* Detects the Redis package version by reading the installed package.json
|
||||
* and sets the appropriate API version (3 for callback-based, 5 for Promise-based).
|
||||
*/
|
||||
private detectRedisVersion(): void {
|
||||
if (this.clientType !== "redis") return
|
||||
|
||||
try {
|
||||
// Detect version by examining the client's method signatures
|
||||
// This avoids creating test keys in the database
|
||||
const setMethod = this.client.set
|
||||
if (setMethod && setMethod.length <= 3) {
|
||||
// Redis 5+ set method accepts fewer parameters (key, value, options)
|
||||
this.redisMajorVersion = 5
|
||||
} else {
|
||||
// Redis 3/4 set method requires more parameters (key, value, flag, duration, callback)
|
||||
this.redisMajorVersion = 3
|
||||
}
|
||||
} catch {
|
||||
// Default to Redis 3/4 for maximum compatibility
|
||||
const version = PlatformTools.readPackageVersion("redis")
|
||||
const major = parseInt(version.split(".")[0], 10)
|
||||
if (isNaN(major)) {
|
||||
throw new TypeORMError(`Invalid Redis version format: ${version}`)
|
||||
}
|
||||
if (major <= 4) {
|
||||
// Redis 3/4 uses callback-based API
|
||||
this.redisMajorVersion = 3
|
||||
} else {
|
||||
// Redis 5+ uses Promise-based API
|
||||
this.redisMajorVersion = 5
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -33,24 +33,23 @@ export interface ContainerInterface {
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
const defaultContainer: ContainerInterface = new (class
|
||||
implements ContainerInterface
|
||||
{
|
||||
private instances: { type: Function; object: any }[] = []
|
||||
const defaultContainer: ContainerInterface =
|
||||
new (class implements ContainerInterface {
|
||||
private instances: { type: Function; object: any }[] = []
|
||||
|
||||
get<T>(someClass: ContainedType<T>): T {
|
||||
let instance = this.instances.find((i) => i.type === someClass)
|
||||
if (!instance) {
|
||||
instance = {
|
||||
type: someClass,
|
||||
object: new (someClass as new () => T)(),
|
||||
get<T>(someClass: ContainedType<T>): T {
|
||||
let instance = this.instances.find((i) => i.type === someClass)
|
||||
if (!instance) {
|
||||
instance = {
|
||||
type: someClass,
|
||||
object: new (someClass as new () => T)(),
|
||||
}
|
||||
this.instances.push(instance)
|
||||
}
|
||||
this.instances.push(instance)
|
||||
}
|
||||
|
||||
return instance.object
|
||||
}
|
||||
})()
|
||||
return instance.object
|
||||
}
|
||||
})()
|
||||
|
||||
let userContainer: ContainerInterface
|
||||
let userContainerOptions: UseContainerOptions | undefined
|
||||
|
||||
@ -200,4 +200,15 @@ export interface ColumnOptions extends ColumnCommonOptions {
|
||||
* @See https://typeorm.io/decorator-reference#virtualcolumn for more details.
|
||||
*/
|
||||
query?: (alias: string) => string
|
||||
|
||||
/**
|
||||
* Indicates if date values should be stored and retrieved in UTC timezone
|
||||
* instead of local timezone. Only applies to "date" column type.
|
||||
* Default value is "false" (uses local timezone for backward compatibility).
|
||||
*
|
||||
* @example
|
||||
* @Column({ type: "date", utc: true })
|
||||
* birthDate: Date
|
||||
*/
|
||||
utc?: boolean
|
||||
}
|
||||
|
||||
@ -7,8 +7,7 @@ import { BaseDataSourceOptions } from "../../data-source/BaseDataSourceOptions"
|
||||
* @see https://github.com/mysqljs/mysql#connection-options
|
||||
*/
|
||||
export interface AuroraMysqlConnectionOptions
|
||||
extends BaseDataSourceOptions,
|
||||
AuroraMysqlConnectionCredentialsOptions {
|
||||
extends BaseDataSourceOptions, AuroraMysqlConnectionCredentialsOptions {
|
||||
/**
|
||||
* Database type.
|
||||
*/
|
||||
|
||||
@ -533,7 +533,9 @@ export class AuroraMysqlDriver implements Driver {
|
||||
if (columnMetadata.type === Boolean) {
|
||||
return value === true ? 1 : 0
|
||||
} else if (columnMetadata.type === "date") {
|
||||
return DateUtils.mixedDateToDateString(value)
|
||||
return DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
return DateUtils.mixedDateToTimeString(value)
|
||||
} else if (columnMetadata.type === "json") {
|
||||
@ -592,7 +594,9 @@ export class AuroraMysqlDriver implements Driver {
|
||||
) {
|
||||
value = DateUtils.normalizeHydratedDate(value)
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value)
|
||||
value = DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "json") {
|
||||
value = typeof value === "string" ? JSON.parse(value) : value
|
||||
} else if (columnMetadata.type === "time") {
|
||||
|
||||
@ -133,7 +133,7 @@ export class BetterSqlite3Driver extends AbstractSqliteDriver {
|
||||
nativeBinding = null,
|
||||
prepareDatabase,
|
||||
} = this.options
|
||||
const databaseConnection = this.sqlite(database, {
|
||||
const databaseConnection = new this.sqlite(database, {
|
||||
readonly,
|
||||
fileMustExist,
|
||||
timeout,
|
||||
@ -143,8 +143,8 @@ export class BetterSqlite3Driver extends AbstractSqliteDriver {
|
||||
// in the options, if encryption key for SQLCipher is setted.
|
||||
// Must invoke key pragma before trying to do any other interaction with the database.
|
||||
if (this.options.key) {
|
||||
databaseConnection.exec(
|
||||
`PRAGMA key = ${JSON.stringify(this.options.key)}`,
|
||||
databaseConnection.pragma(
|
||||
`key = ${JSON.stringify(this.options.key)}`,
|
||||
)
|
||||
}
|
||||
|
||||
@ -155,11 +155,11 @@ export class BetterSqlite3Driver extends AbstractSqliteDriver {
|
||||
|
||||
// we need to enable foreign keys in sqlite to make sure all foreign key related features
|
||||
// working properly. this also makes onDelete to work with sqlite.
|
||||
databaseConnection.exec(`PRAGMA foreign_keys = ON`)
|
||||
databaseConnection.pragma("foreign_keys = ON")
|
||||
|
||||
// turn on WAL mode to enhance performance
|
||||
if (this.options.enableWAL) {
|
||||
databaseConnection.exec(`PRAGMA journal_mode = WAL`)
|
||||
databaseConnection.pragma("journal_mode = WAL")
|
||||
}
|
||||
|
||||
return databaseConnection
|
||||
|
||||
@ -62,14 +62,16 @@ export class BetterSqlite3QueryRunner extends AbstractSqliteQueryRunner {
|
||||
* Called before migrations are run.
|
||||
*/
|
||||
async beforeMigration(): Promise<void> {
|
||||
await this.query(`PRAGMA foreign_keys = OFF`)
|
||||
const databaseConnection = await this.connect()
|
||||
databaseConnection.pragma("foreign_keys = OFF")
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after migrations are run.
|
||||
*/
|
||||
async afterMigration(): Promise<void> {
|
||||
await this.query(`PRAGMA foreign_keys = ON`)
|
||||
const databaseConnection = await this.connect()
|
||||
databaseConnection.pragma("foreign_keys = ON")
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,10 +174,9 @@ export class BetterSqlite3QueryRunner extends AbstractSqliteQueryRunner {
|
||||
}
|
||||
protected async loadPragmaRecords(tablePath: string, pragma: string) {
|
||||
const [database, tableName] = this.splitTablePath(tablePath)
|
||||
const res = await this.query(
|
||||
`PRAGMA ${
|
||||
database ? `"${database}".` : ""
|
||||
}${pragma}("${tableName}")`,
|
||||
const databaseConnection = await this.connect()
|
||||
const res = databaseConnection.pragma(
|
||||
`${database ? `"${database}".` : ""}${pragma}("${tableName}")`,
|
||||
)
|
||||
return res
|
||||
}
|
||||
|
||||
@ -6,8 +6,7 @@ import { CockroachConnectionCredentialsOptions } from "./CockroachConnectionCred
|
||||
* Cockroachdb-specific connection options.
|
||||
*/
|
||||
export interface CockroachConnectionOptions
|
||||
extends BaseDataSourceOptions,
|
||||
CockroachConnectionCredentialsOptions {
|
||||
extends BaseDataSourceOptions, CockroachConnectionCredentialsOptions {
|
||||
/**
|
||||
* Database type.
|
||||
*/
|
||||
|
||||
@ -385,7 +385,9 @@ export class CockroachDriver implements Driver {
|
||||
if (columnMetadata.type === Boolean) {
|
||||
return value === true ? 1 : 0
|
||||
} else if (columnMetadata.type === "date") {
|
||||
return DateUtils.mixedDateToDateString(value)
|
||||
return DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
return DateUtils.mixedDateToTimeString(value)
|
||||
} else if (
|
||||
@ -445,7 +447,9 @@ export class CockroachDriver implements Driver {
|
||||
) {
|
||||
value = DateUtils.normalizeHydratedDate(value)
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value)
|
||||
value = DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
value = DateUtils.mixedTimeToString(value)
|
||||
} else if (columnMetadata.type === "simple-array") {
|
||||
|
||||
@ -472,8 +472,7 @@ export declare class AggregationCursor<
|
||||
|
||||
/** @public */
|
||||
export declare interface AggregationCursorOptions
|
||||
extends AbstractCursorOptions,
|
||||
AggregateOptions {}
|
||||
extends AbstractCursorOptions, AggregateOptions {}
|
||||
|
||||
/**
|
||||
* It is possible to search using alternative types in mongodb e.g.
|
||||
@ -486,25 +485,24 @@ export declare type AlternativeType<T> =
|
||||
|
||||
/** @public */
|
||||
export declare type AnyBulkWriteOperation<TSchema extends Document = Document> =
|
||||
|
||||
| {
|
||||
insertOne: InsertOneModel<TSchema>
|
||||
}
|
||||
| {
|
||||
replaceOne: ReplaceOneModel<TSchema>
|
||||
}
|
||||
| {
|
||||
updateOne: UpdateOneModel<TSchema>
|
||||
}
|
||||
| {
|
||||
updateMany: UpdateManyModel<TSchema>
|
||||
}
|
||||
| {
|
||||
deleteOne: DeleteOneModel<TSchema>
|
||||
}
|
||||
| {
|
||||
deleteMany: DeleteManyModel<TSchema>
|
||||
}
|
||||
| {
|
||||
insertOne: InsertOneModel<TSchema>
|
||||
}
|
||||
| {
|
||||
replaceOne: ReplaceOneModel<TSchema>
|
||||
}
|
||||
| {
|
||||
updateOne: UpdateOneModel<TSchema>
|
||||
}
|
||||
| {
|
||||
updateMany: UpdateManyModel<TSchema>
|
||||
}
|
||||
| {
|
||||
deleteOne: DeleteOneModel<TSchema>
|
||||
}
|
||||
| {
|
||||
deleteMany: DeleteManyModel<TSchema>
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare type AnyError = MongoError | Error
|
||||
@ -826,7 +824,8 @@ export { BSONRegExp }
|
||||
* @public
|
||||
*/
|
||||
export declare interface BSONSerializeOptions
|
||||
extends Omit<SerializeOptions, "index">,
|
||||
extends
|
||||
Omit<SerializeOptions, "index">,
|
||||
Omit<
|
||||
DeserializeOptions,
|
||||
| "evalFunctions"
|
||||
@ -1133,8 +1132,7 @@ export declare class ChangeStream<
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/
|
||||
*/
|
||||
export declare interface ChangeStreamCollModDocument
|
||||
extends ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentCollectionUUID {
|
||||
extends ChangeStreamDocumentCommon, ChangeStreamDocumentCollectionUUID {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
operationType: "modify"
|
||||
}
|
||||
@ -1144,8 +1142,7 @@ export declare interface ChangeStreamCollModDocument
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/
|
||||
*/
|
||||
export declare interface ChangeStreamCreateDocument
|
||||
extends ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentCollectionUUID {
|
||||
extends ChangeStreamDocumentCommon, ChangeStreamDocumentCollectionUUID {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
operationType: "create"
|
||||
}
|
||||
@ -1156,7 +1153,8 @@ export declare interface ChangeStreamCreateDocument
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/
|
||||
*/
|
||||
export declare interface ChangeStreamCreateIndexDocument
|
||||
extends ChangeStreamDocumentCommon,
|
||||
extends
|
||||
ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentCollectionUUID,
|
||||
ChangeStreamDocumentOperationDescription {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
@ -1173,7 +1171,9 @@ export declare interface ChangeStreamCreateIndexDocument
|
||||
*/
|
||||
export declare interface ChangeStreamDeleteDocument<
|
||||
TSchema extends Document = Document,
|
||||
> extends ChangeStreamDocumentCommon,
|
||||
>
|
||||
extends
|
||||
ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentKey<TSchema>,
|
||||
ChangeStreamDocumentCollectionUUID {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
@ -1283,8 +1283,7 @@ export declare interface ChangeStreamDocumentOperationDescription {
|
||||
* @public
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/#dropdatabase-event
|
||||
*/
|
||||
export declare interface ChangeStreamDropDatabaseDocument
|
||||
extends ChangeStreamDocumentCommon {
|
||||
export declare interface ChangeStreamDropDatabaseDocument extends ChangeStreamDocumentCommon {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
operationType: "dropDatabase"
|
||||
/** The database dropped */
|
||||
@ -1298,8 +1297,7 @@ export declare interface ChangeStreamDropDatabaseDocument
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/#drop-event
|
||||
*/
|
||||
export declare interface ChangeStreamDropDocument
|
||||
extends ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentCollectionUUID {
|
||||
extends ChangeStreamDocumentCommon, ChangeStreamDocumentCollectionUUID {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
operationType: "drop"
|
||||
/** Namespace the drop event occurred on */
|
||||
@ -1312,7 +1310,8 @@ export declare interface ChangeStreamDropDocument
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/
|
||||
*/
|
||||
export declare interface ChangeStreamDropIndexDocument
|
||||
extends ChangeStreamDocumentCommon,
|
||||
extends
|
||||
ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentCollectionUUID,
|
||||
ChangeStreamDocumentOperationDescription {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
@ -1339,7 +1338,9 @@ export declare type ChangeStreamEvents<
|
||||
*/
|
||||
export declare interface ChangeStreamInsertDocument<
|
||||
TSchema extends Document = Document,
|
||||
> extends ChangeStreamDocumentCommon,
|
||||
>
|
||||
extends
|
||||
ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentKey<TSchema>,
|
||||
ChangeStreamDocumentCollectionUUID {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
@ -1354,8 +1355,7 @@ export declare interface ChangeStreamInsertDocument<
|
||||
* @public
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/#invalidate-event
|
||||
*/
|
||||
export declare interface ChangeStreamInvalidateDocument
|
||||
extends ChangeStreamDocumentCommon {
|
||||
export declare interface ChangeStreamInvalidateDocument extends ChangeStreamDocumentCommon {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
operationType: "invalidate"
|
||||
}
|
||||
@ -1370,8 +1370,10 @@ export declare interface ChangeStreamNameSpace {
|
||||
* Options that can be passed to a ChangeStream. Note that startAfter, resumeAfter, and startAtOperationTime are all mutually exclusive, and the server will error if more than one is specified.
|
||||
* @public
|
||||
*/
|
||||
export declare interface ChangeStreamOptions
|
||||
extends Omit<AggregateOptions, "writeConcern"> {
|
||||
export declare interface ChangeStreamOptions extends Omit<
|
||||
AggregateOptions,
|
||||
"writeConcern"
|
||||
> {
|
||||
/**
|
||||
* Allowed values: 'updateLookup', 'whenAvailable', 'required'.
|
||||
*
|
||||
@ -1439,7 +1441,8 @@ export declare interface ChangeStreamOptions
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/
|
||||
*/
|
||||
export declare interface ChangeStreamRefineCollectionShardKeyDocument
|
||||
extends ChangeStreamDocumentCommon,
|
||||
extends
|
||||
ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentCollectionUUID,
|
||||
ChangeStreamDocumentOperationDescription {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
@ -1451,8 +1454,7 @@ export declare interface ChangeStreamRefineCollectionShardKeyDocument
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/#rename-event
|
||||
*/
|
||||
export declare interface ChangeStreamRenameDocument
|
||||
extends ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentCollectionUUID {
|
||||
extends ChangeStreamDocumentCommon, ChangeStreamDocumentCollectionUUID {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
operationType: "rename"
|
||||
/** The new name for the `ns.coll` collection */
|
||||
@ -1470,8 +1472,8 @@ export declare interface ChangeStreamRenameDocument
|
||||
*/
|
||||
export declare interface ChangeStreamReplaceDocument<
|
||||
TSchema extends Document = Document,
|
||||
> extends ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentKey<TSchema> {
|
||||
>
|
||||
extends ChangeStreamDocumentCommon, ChangeStreamDocumentKey<TSchema> {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
operationType: "replace"
|
||||
/** The fullDocument of a replace event represents the document after the insert of the replacement document */
|
||||
@ -1493,7 +1495,8 @@ export declare interface ChangeStreamReplaceDocument<
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/
|
||||
*/
|
||||
export declare interface ChangeStreamReshardCollectionDocument
|
||||
extends ChangeStreamDocumentCommon,
|
||||
extends
|
||||
ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentCollectionUUID,
|
||||
ChangeStreamDocumentOperationDescription {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
@ -1505,7 +1508,8 @@ export declare interface ChangeStreamReshardCollectionDocument
|
||||
* @see https://www.mongodb.com/docs/manual/reference/change-events/
|
||||
*/
|
||||
export declare interface ChangeStreamShardCollectionDocument
|
||||
extends ChangeStreamDocumentCommon,
|
||||
extends
|
||||
ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentCollectionUUID,
|
||||
ChangeStreamDocumentOperationDescription {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
@ -1518,7 +1522,9 @@ export declare interface ChangeStreamShardCollectionDocument
|
||||
*/
|
||||
export declare interface ChangeStreamUpdateDocument<
|
||||
TSchema extends Document = Document,
|
||||
> extends ChangeStreamDocumentCommon,
|
||||
>
|
||||
extends
|
||||
ChangeStreamDocumentCommon,
|
||||
ChangeStreamDocumentKey<TSchema>,
|
||||
ChangeStreamDocumentCollectionUUID {
|
||||
/** Describes the type of operation represented in this change notification */
|
||||
@ -2297,8 +2303,7 @@ export declare interface CollectionInfo extends Document {
|
||||
|
||||
/** @public */
|
||||
export declare interface CollectionOptions
|
||||
extends BSONSerializeOptions,
|
||||
WriteConcernOptions {
|
||||
extends BSONSerializeOptions, WriteConcernOptions {
|
||||
/** Specify a read concern for the collection. (only MongoDB 3.2 or higher supported) */
|
||||
readConcern?: ReadConcernLike
|
||||
/** The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). */
|
||||
@ -2387,9 +2392,7 @@ export declare class CommandFailedEvent {
|
||||
|
||||
/** @public */
|
||||
export declare interface CommandOperationOptions
|
||||
extends OperationOptions,
|
||||
WriteConcernOptions,
|
||||
ExplainOptions {
|
||||
extends OperationOptions, WriteConcernOptions, ExplainOptions {
|
||||
/** Specify a read concern and level for the collection. (only MongoDB 3.2 or higher supported) */
|
||||
readConcern?: ReadConcernLike
|
||||
/** Collation */
|
||||
@ -2553,7 +2556,8 @@ export declare type ConnectionEvents = {
|
||||
|
||||
/** @public */
|
||||
export declare interface ConnectionOptions
|
||||
extends SupportedNodeConnectionOptions,
|
||||
extends
|
||||
SupportedNodeConnectionOptions,
|
||||
StreamDescriptionOptions,
|
||||
ProxyOptions {
|
||||
id: number | "<monitor>"
|
||||
@ -2638,8 +2642,10 @@ export declare class ConnectionPoolMonitoringEvent {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface ConnectionPoolOptions
|
||||
extends Omit<ConnectionOptions, "id" | "generation"> {
|
||||
export declare interface ConnectionPoolOptions extends Omit<
|
||||
ConnectionOptions,
|
||||
"id" | "generation"
|
||||
> {
|
||||
/** The maximum number of connections that may be associated with a pool at a given time. This includes in use and available connections. */
|
||||
maxPoolSize: number
|
||||
/** The minimum number of connections that MUST exist at any moment in a single connection pool. */
|
||||
@ -2701,8 +2707,7 @@ export declare interface CountOptions extends CommandOperationOptions {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface CreateCollectionOptions
|
||||
extends CommandOperationOptions {
|
||||
export declare interface CreateCollectionOptions extends CommandOperationOptions {
|
||||
/** Returns an error if the collection does not exist */
|
||||
strict?: boolean
|
||||
/** Create a capped collection */
|
||||
@ -2749,8 +2754,10 @@ export declare interface CreateCollectionOptions
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface CreateIndexesOptions
|
||||
extends Omit<CommandOperationOptions, "writeConcern"> {
|
||||
export declare interface CreateIndexesOptions extends Omit<
|
||||
CommandOperationOptions,
|
||||
"writeConcern"
|
||||
> {
|
||||
/** Creates the index in the background, yielding whenever possible. */
|
||||
background?: boolean
|
||||
/** Creates a unique index. */
|
||||
@ -3054,8 +3061,7 @@ export declare class Db {
|
||||
|
||||
/** @public */
|
||||
export declare interface DbOptions
|
||||
extends BSONSerializeOptions,
|
||||
WriteConcernOptions {
|
||||
extends BSONSerializeOptions, WriteConcernOptions {
|
||||
/** If the database authentication is dependent on another databaseName. */
|
||||
authSource?: string
|
||||
/** Force server to assign _id values instead of driver. */
|
||||
@ -3103,8 +3109,7 @@ export declare interface DeleteOneModel<TSchema extends Document = Document> {
|
||||
|
||||
/** @public */
|
||||
export declare interface DeleteOptions
|
||||
extends CommandOperationOptions,
|
||||
WriteConcernOptions {
|
||||
extends CommandOperationOptions, WriteConcernOptions {
|
||||
/** If true, when an insert fails, don't execute the remaining writes. If false, continue with remaining inserts when one fails. */
|
||||
ordered?: boolean
|
||||
/** Specifies the collation to use for the operation */
|
||||
@ -3194,8 +3199,7 @@ export declare interface ErrorDescription extends Document {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface EstimatedDocumentCountOptions
|
||||
extends CommandOperationOptions {
|
||||
export declare interface EstimatedDocumentCountOptions extends CommandOperationOptions {
|
||||
/**
|
||||
* The maximum amount of time to allow the operation to run.
|
||||
*
|
||||
@ -3263,8 +3267,9 @@ export declare type FilterOperations<T> =
|
||||
: FilterOperators<T>
|
||||
|
||||
/** @public */
|
||||
export declare interface FilterOperators<TValue>
|
||||
extends NonObjectIdLikeDocument {
|
||||
export declare interface FilterOperators<
|
||||
TValue,
|
||||
> extends NonObjectIdLikeDocument {
|
||||
$eq?: TValue
|
||||
$gt?: TValue
|
||||
$gte?: TValue
|
||||
@ -3459,8 +3464,7 @@ export declare class FindCursor<TSchema = any> extends AbstractCursor<TSchema> {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface FindOneAndDeleteOptions
|
||||
extends CommandOperationOptions {
|
||||
export declare interface FindOneAndDeleteOptions extends CommandOperationOptions {
|
||||
/** An optional hint for query optimization. See the {@link https://www.mongodb.com/docs/manual/reference/command/update/#update-command-hint|update command} reference for more information.*/
|
||||
hint?: Document
|
||||
/** Limits the fields to return for all matching documents. */
|
||||
@ -3472,8 +3476,7 @@ export declare interface FindOneAndDeleteOptions
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface FindOneAndReplaceOptions
|
||||
extends CommandOperationOptions {
|
||||
export declare interface FindOneAndReplaceOptions extends CommandOperationOptions {
|
||||
/** Allow driver to bypass schema validation in MongoDB 3.2 or higher. */
|
||||
bypassDocumentValidation?: boolean
|
||||
/** An optional hint for query optimization. See the {@link https://www.mongodb.com/docs/manual/reference/command/update/#update-command-hint|update command} reference for more information.*/
|
||||
@ -3491,8 +3494,7 @@ export declare interface FindOneAndReplaceOptions
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface FindOneAndUpdateOptions
|
||||
extends CommandOperationOptions {
|
||||
export declare interface FindOneAndUpdateOptions extends CommandOperationOptions {
|
||||
/** Optional list of array filters referenced in filtered positional operators */
|
||||
arrayFilters?: Document[]
|
||||
/** Allow driver to bypass schema validation in MongoDB 3.2 or higher. */
|
||||
@ -3544,8 +3546,9 @@ export declare class FindOperators {
|
||||
* @public
|
||||
* @typeParam TSchema - Unused schema definition, deprecated usage, only specify `FindOptions` with no generic
|
||||
*/
|
||||
export declare interface FindOptions<TSchema extends Document = Document>
|
||||
extends Omit<CommandOperationOptions, "writeConcern"> {
|
||||
export declare interface FindOptions<
|
||||
TSchema extends Document = Document,
|
||||
> extends Omit<CommandOperationOptions, "writeConcern"> {
|
||||
/** Sets the limit of documents returned in the query. */
|
||||
limit?: number
|
||||
/** Set to sort the documents coming back from the query. Array of indexes, `[['a', 1]]` etc. */
|
||||
@ -3773,8 +3776,7 @@ export declare interface GridFSBucketReadStreamOptions {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface GridFSBucketReadStreamOptionsWithRevision
|
||||
extends GridFSBucketReadStreamOptions {
|
||||
export declare interface GridFSBucketReadStreamOptionsWithRevision extends GridFSBucketReadStreamOptions {
|
||||
/** The revision number relative to the oldest file with the given filename. 0
|
||||
* gets you the oldest file, 1 gets you the 2nd oldest, -1 gets you the
|
||||
* newest. */
|
||||
@ -3868,8 +3870,7 @@ export declare class GridFSBucketWriteStream {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface GridFSBucketWriteStreamOptions
|
||||
extends WriteConcernOptions {
|
||||
export declare interface GridFSBucketWriteStreamOptions extends WriteConcernOptions {
|
||||
/** Overwrite this bucket's chunkSizeBytes for this file */
|
||||
chunkSizeBytes?: number
|
||||
/** Custom file id for the GridFS file. */
|
||||
@ -3939,28 +3940,27 @@ export declare class HostAddress {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface IndexDescription
|
||||
extends Pick<
|
||||
CreateIndexesOptions,
|
||||
| "background"
|
||||
| "unique"
|
||||
| "partialFilterExpression"
|
||||
| "sparse"
|
||||
| "hidden"
|
||||
| "expireAfterSeconds"
|
||||
| "storageEngine"
|
||||
| "version"
|
||||
| "weights"
|
||||
| "default_language"
|
||||
| "language_override"
|
||||
| "textIndexVersion"
|
||||
| "2dsphereIndexVersion"
|
||||
| "bits"
|
||||
| "min"
|
||||
| "max"
|
||||
| "bucketSize"
|
||||
| "wildcardProjection"
|
||||
> {
|
||||
export declare interface IndexDescription extends Pick<
|
||||
CreateIndexesOptions,
|
||||
| "background"
|
||||
| "unique"
|
||||
| "partialFilterExpression"
|
||||
| "sparse"
|
||||
| "hidden"
|
||||
| "expireAfterSeconds"
|
||||
| "storageEngine"
|
||||
| "version"
|
||||
| "weights"
|
||||
| "default_language"
|
||||
| "language_override"
|
||||
| "textIndexVersion"
|
||||
| "2dsphereIndexVersion"
|
||||
| "bits"
|
||||
| "min"
|
||||
| "max"
|
||||
| "bucketSize"
|
||||
| "wildcardProjection"
|
||||
> {
|
||||
collation?: CollationOptions
|
||||
name?: string
|
||||
key:
|
||||
@ -4254,8 +4254,10 @@ export declare class ListCollectionsCursor<
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface ListCollectionsOptions
|
||||
extends Omit<CommandOperationOptions, "writeConcern"> {
|
||||
export declare interface ListCollectionsOptions extends Omit<
|
||||
CommandOperationOptions,
|
||||
"writeConcern"
|
||||
> {
|
||||
/** Since 4.0: If true, will only return the collection name in the response, and will omit additional info */
|
||||
nameOnly?: boolean
|
||||
/** Since 4.0: If true and nameOnly is true, allows a user without the required privilege (i.e. listCollections action on the database) to run the command when access control is enforced. */
|
||||
@ -4296,8 +4298,10 @@ export declare class ListIndexesCursor extends AbstractCursor {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface ListIndexesOptions
|
||||
extends Omit<CommandOperationOptions, "writeConcern"> {
|
||||
export declare interface ListIndexesOptions extends Omit<
|
||||
CommandOperationOptions,
|
||||
"writeConcern"
|
||||
> {
|
||||
/** The batchSize for the returned command cursor or if pre 2.8 the systems batch collection */
|
||||
batchSize?: number
|
||||
}
|
||||
@ -4571,8 +4575,7 @@ export declare type MongoClientEvents = Pick<
|
||||
* @see https://www.mongodb.com/docs/manual/reference/connection-string
|
||||
*/
|
||||
export declare interface MongoClientOptions
|
||||
extends BSONSerializeOptions,
|
||||
SupportedNodeConnectionOptions {
|
||||
extends BSONSerializeOptions, SupportedNodeConnectionOptions {
|
||||
/** Specifies the name of the replica set, if the mongod is a member of a replica set. */
|
||||
replicaSet?: string
|
||||
/** Enables or disables TLS/SSL for the connection. */
|
||||
@ -5044,7 +5047,8 @@ export declare class MongoNotConnectedError extends MongoAPIError {
|
||||
* @public
|
||||
*/
|
||||
export declare interface MongoOptions
|
||||
extends Required<
|
||||
extends
|
||||
Required<
|
||||
Pick<
|
||||
MongoClientOptions,
|
||||
| "autoEncryption"
|
||||
@ -5283,8 +5287,10 @@ export declare type MonitorEvents = {
|
||||
/* Excluded from this release type: MonitorIntervalOptions */
|
||||
|
||||
/** @public */
|
||||
export declare interface MonitorOptions
|
||||
extends Omit<ConnectionOptions, "id" | "generation" | "hostAddress"> {
|
||||
export declare interface MonitorOptions extends Omit<
|
||||
ConnectionOptions,
|
||||
"id" | "generation" | "hostAddress"
|
||||
> {
|
||||
connectTimeoutMS: number
|
||||
heartbeatFrequencyMS: number
|
||||
minHeartbeatFrequencyMS: number
|
||||
@ -5713,8 +5719,7 @@ export declare class ReadPreference {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface ReadPreferenceFromOptions
|
||||
extends ReadPreferenceLikeOptions {
|
||||
export declare interface ReadPreferenceFromOptions extends ReadPreferenceLikeOptions {
|
||||
session?: ClientSession
|
||||
readPreferenceTags?: TagSet[]
|
||||
hedge?: HedgeOptions
|
||||
@ -5724,8 +5729,7 @@ export declare interface ReadPreferenceFromOptions
|
||||
export declare type ReadPreferenceLike = ReadPreference | ReadPreferenceMode
|
||||
|
||||
/** @public */
|
||||
export declare interface ReadPreferenceLikeOptions
|
||||
extends ReadPreferenceOptions {
|
||||
export declare interface ReadPreferenceLikeOptions extends ReadPreferenceOptions {
|
||||
readPreference?:
|
||||
| ReadPreferenceLike
|
||||
| {
|
||||
@ -6511,8 +6515,9 @@ export declare interface TransactionOptions extends CommandOperationOptions {
|
||||
* Typescript type safe event emitter
|
||||
* @public
|
||||
*/
|
||||
export declare interface TypedEventEmitter<Events extends EventsDescription>
|
||||
extends EventEmitter {
|
||||
export declare interface TypedEventEmitter<
|
||||
Events extends EventsDescription,
|
||||
> extends EventEmitter {
|
||||
addListener<EventKey extends keyof Events>(
|
||||
event: EventKey,
|
||||
listener: Events[EventKey],
|
||||
@ -6800,8 +6805,7 @@ export declare interface UpdateStatement {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export declare interface ValidateCollectionOptions
|
||||
extends CommandOperationOptions {
|
||||
export declare interface ValidateCollectionOptions extends CommandOperationOptions {
|
||||
/** Validates a collection in the background, without interrupting read or write traffic (only in MongoDB 4.4+) */
|
||||
background?: boolean
|
||||
}
|
||||
|
||||
@ -43,4 +43,10 @@ export interface MysqlConnectionCredentialsOptions {
|
||||
* Database socket path
|
||||
*/
|
||||
readonly socketPath?: string
|
||||
|
||||
/**
|
||||
* Maximum number of clients the pool should contain.
|
||||
* for each connection
|
||||
*/
|
||||
readonly poolSize?: number
|
||||
}
|
||||
|
||||
@ -8,8 +8,7 @@ import { MysqlConnectionCredentialsOptions } from "./MysqlConnectionCredentialsO
|
||||
* @see https://github.com/mysqljs/mysql#connection-options
|
||||
*/
|
||||
export interface MysqlConnectionOptions
|
||||
extends BaseDataSourceOptions,
|
||||
MysqlConnectionCredentialsOptions {
|
||||
extends BaseDataSourceOptions, MysqlConnectionCredentialsOptions {
|
||||
/**
|
||||
* Database type.
|
||||
*/
|
||||
@ -17,8 +16,7 @@ export interface MysqlConnectionOptions
|
||||
|
||||
/**
|
||||
* The driver object
|
||||
* This defaults to require("mysql").
|
||||
* Falls back to require("mysql2")
|
||||
* This defaults to require("mysql2").
|
||||
*/
|
||||
readonly driver?: any
|
||||
|
||||
@ -103,12 +101,6 @@ export interface MysqlConnectionOptions
|
||||
*/
|
||||
readonly flags?: string[]
|
||||
|
||||
/**
|
||||
* TypeORM will automatically use package found in your node_modules, prioritizing mysql over mysql2,
|
||||
* but you can specify it manually
|
||||
*/
|
||||
readonly connectorPackage?: "mysql" | "mysql2"
|
||||
|
||||
/**
|
||||
* If a value is specified for maxQueryExecutionTime, in addition to generating a warning log when a query exceeds this time limit,
|
||||
* the specified maxQueryExecutionTime value is also used as the timeout for the query.
|
||||
|
||||
@ -57,11 +57,6 @@ export class MysqlDriver implements Driver {
|
||||
*/
|
||||
poolCluster: any
|
||||
|
||||
/**
|
||||
* The actual connector package that was loaded ("mysql" or "mysql2").
|
||||
*/
|
||||
private loadedConnectorPackage: "mysql" | "mysql2" | undefined
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Implemented Properties
|
||||
// -------------------------------------------------------------------------
|
||||
@ -157,6 +152,8 @@ export class MysqlDriver implements Driver {
|
||||
"multilinestring",
|
||||
"multipolygon",
|
||||
"geometrycollection",
|
||||
// vector data types
|
||||
"vector",
|
||||
// additional data types for mariadb
|
||||
"uuid",
|
||||
"inet4",
|
||||
@ -191,6 +188,7 @@ export class MysqlDriver implements Driver {
|
||||
"nvarchar",
|
||||
"binary",
|
||||
"varbinary",
|
||||
"vector",
|
||||
]
|
||||
|
||||
/**
|
||||
@ -280,6 +278,7 @@ export class MysqlDriver implements Driver {
|
||||
char: { length: 1 },
|
||||
binary: { length: 1 },
|
||||
varbinary: { length: 255 },
|
||||
vector: { length: 2048 }, // default length MySQL uses if not provided a value
|
||||
decimal: { precision: 10, scale: 0 },
|
||||
dec: { precision: 10, scale: 0 },
|
||||
numeric: { precision: 10, scale: 0 },
|
||||
@ -589,14 +588,6 @@ export class MysqlDriver implements Driver {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the driver is using mysql2 package.
|
||||
*/
|
||||
protected isUsingMysql2(): boolean {
|
||||
// Check which package was actually loaded during initialization
|
||||
return this.loadedConnectorPackage === "mysql2"
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares given value to a value to be persisted, based on its column type and metadata.
|
||||
*/
|
||||
@ -612,7 +603,9 @@ export class MysqlDriver implements Driver {
|
||||
if (columnMetadata.type === Boolean) {
|
||||
return value === true ? 1 : 0
|
||||
} else if (columnMetadata.type === "date") {
|
||||
return DateUtils.mixedDateToDateString(value)
|
||||
return DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
return DateUtils.mixedDateToTimeString(value)
|
||||
} else if (columnMetadata.type === "json") {
|
||||
@ -666,29 +659,23 @@ export class MysqlDriver implements Driver {
|
||||
) {
|
||||
value = DateUtils.normalizeHydratedDate(value)
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value)
|
||||
value = DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "json") {
|
||||
// mysql2 returns JSON values already parsed, but may still be a string
|
||||
// if the JSON value itself is a string (e.g., "\"hello\"")
|
||||
// mysql (classic) always returns JSON as strings that need parsing
|
||||
if (this.isUsingMysql2()) {
|
||||
// With mysql2, only parse if it's a valid JSON string representation
|
||||
// but not if it's already an object or a JSON primitive
|
||||
if (typeof value === "string") {
|
||||
try {
|
||||
// Try to parse it - if it fails, it's already a parsed string value
|
||||
const parsed = JSON.parse(value)
|
||||
value = parsed
|
||||
} catch {
|
||||
// It's a string that's not valid JSON, which means mysql2
|
||||
// already parsed it and it's just a string value
|
||||
// Keep value as is
|
||||
}
|
||||
// mysql2 only parse if it's a valid JSON string representation
|
||||
// but not if it's already an object or a JSON primitive
|
||||
// If it's not a string, mysql2 has already parsed it correctly
|
||||
if (typeof value === "string") {
|
||||
try {
|
||||
// Try to parse it - if it fails, it's already a parsed string value
|
||||
const parsed = JSON.parse(value)
|
||||
value = parsed
|
||||
} catch {
|
||||
// It's a string that's not valid JSON, which means mysql2
|
||||
// already parsed it and it's just a string value
|
||||
// Keep value as is
|
||||
}
|
||||
// If it's not a string, mysql2 has already parsed it correctly
|
||||
} else {
|
||||
// Classic mysql always returns JSON as strings
|
||||
value = typeof value === "string" ? JSON.parse(value) : value
|
||||
}
|
||||
} else if (columnMetadata.type === "time") {
|
||||
value = DateUtils.mixedTimeToString(value)
|
||||
@ -1188,64 +1175,10 @@ export class MysqlDriver implements Driver {
|
||||
* Loads all driver dependencies.
|
||||
*/
|
||||
protected loadDependencies(): void {
|
||||
// Warn if driver is provided directly but connectorPackage is not specified
|
||||
if (this.options.driver && !this.options.connectorPackage) {
|
||||
console.warn(
|
||||
"Warning: MySQL driver instance provided directly without specifying connectorPackage. " +
|
||||
"This may lead to unexpected JSON parsing behavior differences between mysql and mysql2. " +
|
||||
"Consider explicitly setting connectorPackage: 'mysql' or 'mysql2' in your configuration.",
|
||||
)
|
||||
}
|
||||
|
||||
const connectorPackage = this.options.connectorPackage ?? "mysql"
|
||||
const fallbackConnectorPackage =
|
||||
connectorPackage === "mysql"
|
||||
? ("mysql2" as const)
|
||||
: ("mysql" as const)
|
||||
try {
|
||||
// try to load first supported package
|
||||
const mysql =
|
||||
this.options.driver || PlatformTools.load(connectorPackage)
|
||||
this.mysql = mysql
|
||||
/*
|
||||
* Some frameworks (such as Jest) may mess up Node's require cache and provide garbage for the 'mysql' module
|
||||
* if it was not installed. We check that the object we got actually contains something otherwise we treat
|
||||
* it as if the `require` call failed.
|
||||
*
|
||||
* @see https://github.com/typeorm/typeorm/issues/1373
|
||||
*/
|
||||
if (Object.keys(this.mysql).length === 0) {
|
||||
throw new TypeORMError(
|
||||
`'${connectorPackage}' was found but it is empty. Falling back to '${fallbackConnectorPackage}'.`,
|
||||
)
|
||||
}
|
||||
// Successfully loaded the requested package
|
||||
// If driver was provided directly, try to detect which package it is
|
||||
if (this.options.driver && !this.options.connectorPackage) {
|
||||
// Try to detect if it's mysql2 based on unique properties
|
||||
if (
|
||||
this.mysql.version ||
|
||||
(this.mysql.Connection &&
|
||||
this.mysql.Connection.prototype.execute)
|
||||
) {
|
||||
this.loadedConnectorPackage = "mysql2"
|
||||
} else {
|
||||
this.loadedConnectorPackage = "mysql"
|
||||
}
|
||||
} else {
|
||||
this.loadedConnectorPackage = connectorPackage
|
||||
}
|
||||
this.mysql = this.options.driver || PlatformTools.load("mysql2")
|
||||
} catch (e) {
|
||||
try {
|
||||
this.mysql = PlatformTools.load(fallbackConnectorPackage) // try to load second supported package
|
||||
// Successfully loaded the fallback package
|
||||
this.loadedConnectorPackage = fallbackConnectorPackage
|
||||
} catch (e) {
|
||||
throw new DriverPackageNotInstalledError(
|
||||
"Mysql",
|
||||
connectorPackage,
|
||||
)
|
||||
}
|
||||
throw new DriverPackageNotInstalledError("Mysql", "mysql2")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1293,7 +1226,7 @@ export class MysqlDriver implements Driver {
|
||||
port: credentials.port,
|
||||
ssl: options.ssl,
|
||||
socketPath: credentials.socketPath,
|
||||
connectionLimit: options.poolSize,
|
||||
connectionLimit: credentials.poolSize ?? options.poolSize,
|
||||
},
|
||||
options.acquireTimeout === undefined
|
||||
? {}
|
||||
|
||||
@ -2800,17 +2800,19 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
|
||||
) !== -1 &&
|
||||
dbColumn["CHARACTER_MAXIMUM_LENGTH"]
|
||||
) {
|
||||
const length =
|
||||
dbColumn[
|
||||
"CHARACTER_MAXIMUM_LENGTH"
|
||||
].toString()
|
||||
let length: number =
|
||||
dbColumn["CHARACTER_MAXIMUM_LENGTH"]
|
||||
if (tableColumn.type === "vector") {
|
||||
// MySQL and MariaDb store the vector length in bytes, not in number of dimensions.
|
||||
length = length / 4
|
||||
}
|
||||
tableColumn.length =
|
||||
!this.isDefaultColumnLength(
|
||||
table,
|
||||
tableColumn,
|
||||
length,
|
||||
length.toString(),
|
||||
)
|
||||
? length
|
||||
? length.toString()
|
||||
: ""
|
||||
}
|
||||
|
||||
|
||||
@ -13,8 +13,7 @@ export interface OracleThickModeOptions {
|
||||
* Oracle-specific connection options.
|
||||
*/
|
||||
export interface OracleConnectionOptions
|
||||
extends BaseDataSourceOptions,
|
||||
OracleConnectionCredentialsOptions {
|
||||
extends BaseDataSourceOptions, OracleConnectionCredentialsOptions {
|
||||
/**
|
||||
* Database type.
|
||||
*/
|
||||
|
||||
@ -531,9 +531,9 @@ export class OracleDriver implements Driver {
|
||||
} else if (columnMetadata.type === "date") {
|
||||
if (typeof value === "string") value = value.replace(/[^0-9-]/g, "")
|
||||
return () =>
|
||||
`TO_DATE('${DateUtils.mixedDateToDateString(
|
||||
value,
|
||||
)}', 'YYYY-MM-DD')`
|
||||
`TO_DATE('${DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})}', 'YYYY-MM-DD')`
|
||||
} else if (
|
||||
columnMetadata.type === Date ||
|
||||
columnMetadata.type === "timestamp" ||
|
||||
@ -567,7 +567,9 @@ export class OracleDriver implements Driver {
|
||||
if (columnMetadata.type === Boolean) {
|
||||
value = !!value
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value)
|
||||
value = DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
value = DateUtils.mixedTimeToString(value)
|
||||
} else if (
|
||||
|
||||
@ -6,8 +6,7 @@ import { PostgresConnectionCredentialsOptions } from "./PostgresConnectionCreden
|
||||
* Postgres-specific connection options.
|
||||
*/
|
||||
export interface PostgresConnectionOptions
|
||||
extends BaseDataSourceOptions,
|
||||
PostgresConnectionCredentialsOptions {
|
||||
extends BaseDataSourceOptions, PostgresConnectionCredentialsOptions {
|
||||
/**
|
||||
* Database type.
|
||||
*/
|
||||
|
||||
@ -656,7 +656,9 @@ export class PostgresDriver implements Driver {
|
||||
if (columnMetadata.type === Boolean) {
|
||||
return value === true ? 1 : 0
|
||||
} else if (columnMetadata.type === "date") {
|
||||
return DateUtils.mixedDateToDateString(value)
|
||||
return DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
return DateUtils.mixedDateToTimeString(value)
|
||||
} else if (
|
||||
@ -755,7 +757,9 @@ export class PostgresDriver implements Driver {
|
||||
) {
|
||||
value = DateUtils.normalizeHydratedDate(value)
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value)
|
||||
value = DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
value = DateUtils.mixedTimeToString(value)
|
||||
} else if (
|
||||
|
||||
@ -335,7 +335,9 @@ export class ReactNativeDriver implements Driver {
|
||||
) {
|
||||
return value === true ? 1 : 0
|
||||
} else if (columnMetadata.type === "date") {
|
||||
return DateUtils.mixedDateToDateString(value)
|
||||
return DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
return DateUtils.mixedDateToTimeString(value)
|
||||
} else if (
|
||||
@ -407,7 +409,9 @@ export class ReactNativeDriver implements Driver {
|
||||
|
||||
value = DateUtils.normalizeHydratedDate(value)
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value)
|
||||
value = DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
value = DateUtils.mixedTimeToString(value)
|
||||
} else if (columnMetadata.type === "simple-array") {
|
||||
|
||||
@ -5,8 +5,7 @@ import { SapConnectionCredentialsOptions } from "./SapConnectionCredentialsOptio
|
||||
* SAP Hana specific connection options.
|
||||
*/
|
||||
export interface SapConnectionOptions
|
||||
extends BaseDataSourceOptions,
|
||||
SapConnectionCredentialsOptions {
|
||||
extends BaseDataSourceOptions, SapConnectionCredentialsOptions {
|
||||
/**
|
||||
* Database type.
|
||||
*/
|
||||
|
||||
@ -542,7 +542,9 @@ export class SapDriver implements Driver {
|
||||
if (value === null || value === undefined) return value
|
||||
|
||||
if (columnMetadata.type === "date") {
|
||||
return DateUtils.mixedDateToDateString(value)
|
||||
return DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
return DateUtils.mixedDateToTimeString(value)
|
||||
} else if (
|
||||
@ -584,7 +586,9 @@ export class SapDriver implements Driver {
|
||||
) {
|
||||
value = DateUtils.normalizeHydratedDate(value)
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value)
|
||||
value = DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
value = DateUtils.mixedTimeToString(value)
|
||||
} else if (columnMetadata.type === "simple-array") {
|
||||
|
||||
@ -6,8 +6,7 @@ import { SpannerConnectionCredentialsOptions } from "./SpannerConnectionCredenti
|
||||
* Spanner specific connection options.
|
||||
*/
|
||||
export interface SpannerConnectionOptions
|
||||
extends BaseConnectionOptions,
|
||||
SpannerConnectionCredentialsOptions {
|
||||
extends BaseConnectionOptions, SpannerConnectionCredentialsOptions {
|
||||
/**
|
||||
* Database type.
|
||||
*/
|
||||
|
||||
@ -399,7 +399,9 @@ export class SpannerDriver implements Driver {
|
||||
const lib = this.options.driver || PlatformTools.load("spanner")
|
||||
return lib.Spanner.numeric(value.toString())
|
||||
} else if (columnMetadata.type === "date") {
|
||||
return DateUtils.mixedDateToDateString(value)
|
||||
return DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "json") {
|
||||
return value
|
||||
} else if (
|
||||
@ -434,7 +436,9 @@ export class SpannerDriver implements Driver {
|
||||
} else if (columnMetadata.type === "numeric") {
|
||||
value = value.value
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value)
|
||||
value = DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "json") {
|
||||
value = typeof value === "string" ? JSON.parse(value) : value
|
||||
} else if (columnMetadata.type === Number) {
|
||||
|
||||
@ -331,7 +331,9 @@ export abstract class AbstractSqliteDriver implements Driver {
|
||||
) {
|
||||
return value === true ? 1 : 0
|
||||
} else if (columnMetadata.type === "date") {
|
||||
return DateUtils.mixedDateToDateString(value)
|
||||
return DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
return DateUtils.mixedDateToTimeString(value)
|
||||
} else if (
|
||||
@ -406,7 +408,9 @@ export abstract class AbstractSqliteDriver implements Driver {
|
||||
|
||||
value = DateUtils.normalizeHydratedDate(value)
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value)
|
||||
value = DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
value = DateUtils.mixedTimeToString(value)
|
||||
} else if (
|
||||
|
||||
@ -6,8 +6,7 @@ import { SqlServerConnectionCredentialsOptions } from "./SqlServerConnectionCred
|
||||
* Microsoft Sql Server specific connection options.
|
||||
*/
|
||||
export interface SqlServerConnectionOptions
|
||||
extends BaseDataSourceOptions,
|
||||
SqlServerConnectionCredentialsOptions {
|
||||
extends BaseDataSourceOptions, SqlServerConnectionCredentialsOptions {
|
||||
/**
|
||||
* Database type.
|
||||
*/
|
||||
|
||||
@ -532,7 +532,7 @@ export class SqlServerDriver implements Driver {
|
||||
if (columnMetadata.type === Boolean) {
|
||||
return value === true ? 1 : 0
|
||||
} else if (columnMetadata.type === "date") {
|
||||
return DateUtils.mixedDateToDate(value)
|
||||
return DateUtils.mixedDateToDate(value, columnMetadata.utc)
|
||||
} else if (columnMetadata.type === "time") {
|
||||
return DateUtils.mixedTimeToDate(value)
|
||||
} else if (
|
||||
@ -586,7 +586,9 @@ export class SqlServerDriver implements Driver {
|
||||
) {
|
||||
value = DateUtils.normalizeHydratedDate(value)
|
||||
} else if (columnMetadata.type === "date") {
|
||||
value = DateUtils.mixedDateToDateString(value)
|
||||
value = DateUtils.mixedDateToDateString(value, {
|
||||
utc: columnMetadata.utc,
|
||||
})
|
||||
} else if (columnMetadata.type === "time") {
|
||||
value = DateUtils.mixedTimeToString(value)
|
||||
} else if (columnMetadata.type === "simple-array") {
|
||||
|
||||
@ -75,7 +75,7 @@ export type WithLengthColumnType =
|
||||
| "binary" // mssql
|
||||
| "varbinary" // mssql, sap
|
||||
| "string" // cockroachdb, spanner
|
||||
| "vector" // postgres, mssql, sap
|
||||
| "vector" // mariadb, mysql, mssql, postgres, sap
|
||||
| "halfvec" // postgres, sap
|
||||
| "half_vector" // sap
|
||||
| "real_vector" // sap
|
||||
|
||||
@ -971,7 +971,7 @@ export class EntityManager {
|
||||
/**
|
||||
* Checks whether any entity exists with the given options.
|
||||
*/
|
||||
exists<Entity extends ObjectLiteral>(
|
||||
async exists<Entity extends ObjectLiteral>(
|
||||
entityClass: EntityTarget<Entity>,
|
||||
options?: FindManyOptions<Entity>,
|
||||
): Promise<boolean> {
|
||||
@ -1002,7 +1002,7 @@ export class EntityManager {
|
||||
* Counts entities that match given options.
|
||||
* Useful for pagination.
|
||||
*/
|
||||
count<Entity extends ObjectLiteral>(
|
||||
async count<Entity extends ObjectLiteral>(
|
||||
entityClass: EntityTarget<Entity>,
|
||||
options?: FindManyOptions<Entity>,
|
||||
): Promise<number> {
|
||||
@ -1020,7 +1020,7 @@ export class EntityManager {
|
||||
* Counts entities that match given conditions.
|
||||
* Useful for pagination.
|
||||
*/
|
||||
countBy<Entity extends ObjectLiteral>(
|
||||
async countBy<Entity extends ObjectLiteral>(
|
||||
entityClass: EntityTarget<Entity>,
|
||||
where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
|
||||
): Promise<number> {
|
||||
@ -1090,12 +1090,16 @@ export class EntityManager {
|
||||
)
|
||||
}
|
||||
|
||||
const result = await this.createQueryBuilder(entityClass, metadata.name)
|
||||
.setFindOptions({ where })
|
||||
const qb = this.createQueryBuilder(entityClass, metadata.name)
|
||||
qb.setFindOptions({ where })
|
||||
|
||||
const alias = qb.alias
|
||||
|
||||
const result = await qb
|
||||
.select(
|
||||
`${fnName}(${this.connection.driver.escape(
|
||||
column.databaseName,
|
||||
)})`,
|
||||
alias,
|
||||
)}.${this.connection.driver.escape(column.databaseName)})`,
|
||||
fnName,
|
||||
)
|
||||
.getRawOne()
|
||||
@ -1140,7 +1144,7 @@ export class EntityManager {
|
||||
* Also counts all entities that match given conditions,
|
||||
* but ignores pagination settings (from and take options).
|
||||
*/
|
||||
findAndCount<Entity extends ObjectLiteral>(
|
||||
async findAndCount<Entity extends ObjectLiteral>(
|
||||
entityClass: EntityTarget<Entity>,
|
||||
options?: FindManyOptions<Entity>,
|
||||
): Promise<[Entity[], number]> {
|
||||
@ -1159,7 +1163,7 @@ export class EntityManager {
|
||||
* Also counts all entities that match given conditions,
|
||||
* but ignores pagination settings (from and take options).
|
||||
*/
|
||||
findAndCountBy<Entity extends ObjectLiteral>(
|
||||
async findAndCountBy<Entity extends ObjectLiteral>(
|
||||
entityClass: EntityTarget<Entity>,
|
||||
where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
|
||||
): Promise<[Entity[], number]> {
|
||||
|
||||
@ -15,46 +15,46 @@ import { DeleteResult } from "../query-builder/result/DeleteResult"
|
||||
import { EntityMetadata } from "../metadata/EntityMetadata"
|
||||
|
||||
import {
|
||||
BulkWriteResult,
|
||||
AggregationCursor,
|
||||
Collection,
|
||||
FindCursor,
|
||||
Document,
|
||||
AggregateOptions,
|
||||
AggregationCursor,
|
||||
AnyBulkWriteOperation,
|
||||
BulkWriteOptions,
|
||||
Filter,
|
||||
CountOptions,
|
||||
IndexSpecification,
|
||||
CreateIndexesOptions,
|
||||
IndexDescription,
|
||||
DeleteResult as DeleteResultMongoDb,
|
||||
DeleteOptions,
|
||||
CommandOperationOptions,
|
||||
FindOneAndDeleteOptions,
|
||||
FindOneAndReplaceOptions,
|
||||
UpdateFilter,
|
||||
FindOneAndUpdateOptions,
|
||||
RenameOptions,
|
||||
ReplaceOptions,
|
||||
UpdateResult as UpdateResultMongoDb,
|
||||
BulkWriteResult,
|
||||
ChangeStream,
|
||||
ChangeStreamOptions,
|
||||
Collection,
|
||||
CollStats,
|
||||
CollStatsOptions,
|
||||
ChangeStreamOptions,
|
||||
ChangeStream,
|
||||
UpdateOptions,
|
||||
ListIndexesOptions,
|
||||
ListIndexesCursor,
|
||||
OptionalId,
|
||||
CommandOperationOptions,
|
||||
CountDocumentsOptions,
|
||||
CountOptions,
|
||||
CreateIndexesOptions,
|
||||
DeleteOptions,
|
||||
DeleteResult as DeleteResultMongoDb,
|
||||
Document,
|
||||
Filter,
|
||||
FilterOperators,
|
||||
FindCursor,
|
||||
FindOneAndDeleteOptions,
|
||||
FindOneAndReplaceOptions,
|
||||
FindOneAndUpdateOptions,
|
||||
IndexDescription,
|
||||
IndexInformationOptions,
|
||||
IndexSpecification,
|
||||
InsertManyResult,
|
||||
InsertOneOptions,
|
||||
InsertOneResult,
|
||||
InsertManyResult,
|
||||
UnorderedBulkOperation,
|
||||
OrderedBulkOperation,
|
||||
IndexInformationOptions,
|
||||
ListIndexesCursor,
|
||||
ListIndexesOptions,
|
||||
ObjectId,
|
||||
FilterOperators,
|
||||
CountDocumentsOptions,
|
||||
OptionalId,
|
||||
OrderedBulkOperation,
|
||||
RenameOptions,
|
||||
ReplaceOptions,
|
||||
UnorderedBulkOperation,
|
||||
UpdateFilter,
|
||||
UpdateOptions,
|
||||
UpdateResult as UpdateResultMongoDb,
|
||||
} from "../driver/mongodb/typings"
|
||||
import { DataSource } from "../data-source/DataSource"
|
||||
import { MongoFindManyOptions } from "../find-options/mongodb/MongoFindManyOptions"
|
||||
@ -161,6 +161,16 @@ export class MongoEntityManager extends EntityManager {
|
||||
return this.executeFindAndCount(entityClassOrName, where)
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds entities that match given WHERE conditions.
|
||||
*/
|
||||
async findBy<Entity>(
|
||||
entityClassOrName: EntityTarget<Entity>,
|
||||
where: any,
|
||||
): Promise<Entity[]> {
|
||||
return this.executeFind(entityClassOrName, where)
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds entities by ids.
|
||||
* Optionally find options can be applied.
|
||||
|
||||
@ -3,8 +3,9 @@ import { MongoFindOneOptions } from "./MongoFindOneOptions"
|
||||
/**
|
||||
* Defines a special criteria to find specific entities.
|
||||
*/
|
||||
export interface MongoFindManyOptions<Entity = any>
|
||||
extends MongoFindOneOptions<Entity> {
|
||||
export interface MongoFindManyOptions<
|
||||
Entity = any,
|
||||
> extends MongoFindOneOptions<Entity> {
|
||||
/**
|
||||
* Offset (paginated) where from entities should be taken.
|
||||
*/
|
||||
|
||||
@ -123,6 +123,12 @@ export class ColumnMetadata {
|
||||
*/
|
||||
comment?: string
|
||||
|
||||
/**
|
||||
* Indicates if date values use UTC timezone.
|
||||
* Only applies to "date" column type.
|
||||
*/
|
||||
utc: boolean = false
|
||||
|
||||
/**
|
||||
* Default database value.
|
||||
*/
|
||||
@ -388,6 +394,8 @@ export class ColumnMetadata {
|
||||
this.isSelect = options.args.options.select
|
||||
if (options.args.options.insert !== undefined)
|
||||
this.isInsert = options.args.options.insert
|
||||
if (options.args.options.utc !== undefined)
|
||||
this.utc = options.args.options.utc
|
||||
if (options.args.options.update !== undefined)
|
||||
this.isUpdate = options.args.options.update
|
||||
if (options.args.options.readonly !== undefined)
|
||||
|
||||
@ -12,6 +12,7 @@ import { PropertyTypeFactory } from "./types/PropertyTypeInFunction"
|
||||
import { TypeORMError } from "../error"
|
||||
import { ObjectUtils } from "../util/ObjectUtils"
|
||||
import { InstanceChecker } from "../util/InstanceChecker"
|
||||
import { OrmUtils } from "../util/OrmUtils"
|
||||
|
||||
/**
|
||||
* Contains all information about some entity's relation.
|
||||
@ -520,7 +521,11 @@ export class RelationMetadata {
|
||||
entity,
|
||||
)
|
||||
} else {
|
||||
entity[propertyName] = value
|
||||
if (ObjectUtils.isObject(entity[propertyName])) {
|
||||
OrmUtils.mergeDeep(entity[propertyName], value)
|
||||
} else {
|
||||
entity[propertyName] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -414,6 +414,8 @@ export class MigrationExecutor {
|
||||
this.connection.logger.logSchemaBuild(
|
||||
`No migrations were found in the database. Nothing to revert!`,
|
||||
)
|
||||
// if query runner was created by us then release it
|
||||
if (!this.queryRunner) await queryRunner.release()
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -27,6 +27,20 @@ export class PlatformTools {
|
||||
return global
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the version string from package.json of the given package.
|
||||
* This operation is only supported in node.
|
||||
*/
|
||||
static readPackageVersion(name: string): string {
|
||||
try {
|
||||
return require(`${name}/package.json`).version
|
||||
} catch (err) {
|
||||
throw new TypeError(
|
||||
`Failed to read package.json for "${name}": ${err.message}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads ("require"-s) given file or package.
|
||||
* This operation only supports on node platform
|
||||
@ -63,9 +77,6 @@ export class PlatformTools {
|
||||
/**
|
||||
* mysql
|
||||
*/
|
||||
case "mysql":
|
||||
return require("mysql")
|
||||
|
||||
case "mysql2":
|
||||
return require("mysql2")
|
||||
|
||||
|
||||
@ -25,8 +25,21 @@ export class DateUtils {
|
||||
/**
|
||||
* Converts given value into date string in a "YYYY-MM-DD" format.
|
||||
*/
|
||||
static mixedDateToDateString(value: string | Date): string {
|
||||
static mixedDateToDateString(
|
||||
value: string | Date,
|
||||
options?: { utc?: boolean },
|
||||
): string {
|
||||
const utc = options?.utc ?? false
|
||||
if (value instanceof Date) {
|
||||
if (utc) {
|
||||
return (
|
||||
this.formatZerolessValue(value.getUTCFullYear(), 4) +
|
||||
"-" +
|
||||
this.formatZerolessValue(value.getUTCMonth() + 1) +
|
||||
"-" +
|
||||
this.formatZerolessValue(value.getUTCDate())
|
||||
)
|
||||
}
|
||||
return (
|
||||
this.formatZerolessValue(value.getFullYear(), 4) +
|
||||
"-" +
|
||||
|
||||
@ -12,6 +12,7 @@ describe("benchmark > bulk-sql-build", () => {
|
||||
before(async () => {
|
||||
dataSources = await createTestingConnections({
|
||||
__dirname,
|
||||
enabledDrivers: ["postgres"],
|
||||
})
|
||||
})
|
||||
beforeEach(() => reloadTestingDatabases(dataSources))
|
||||
@ -1,11 +1,11 @@
|
||||
import { expect } from "chai"
|
||||
import "reflect-metadata"
|
||||
import { scheduler } from "timers/promises"
|
||||
import { DataSource } from "../../../../src"
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
sleep,
|
||||
} from "../../../utils/test-utils"
|
||||
import { Post } from "./entity/Post"
|
||||
|
||||
@ -81,7 +81,7 @@ describe("column kinds > create date column", () => {
|
||||
})
|
||||
|
||||
// wait a second
|
||||
await sleep(1000)
|
||||
await scheduler.wait(1010)
|
||||
|
||||
// create post once again
|
||||
post.title = "Updated Title"
|
||||
@ -1,11 +1,11 @@
|
||||
import { expect } from "chai"
|
||||
import "reflect-metadata"
|
||||
import { scheduler } from "timers/promises"
|
||||
import { DataSource } from "../../../../src"
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
sleep,
|
||||
} from "../../../utils/test-utils"
|
||||
import { Post } from "./entity/Post"
|
||||
|
||||
@ -109,7 +109,7 @@ describe("column kinds > update date column", () => {
|
||||
})
|
||||
|
||||
// wait a second
|
||||
await sleep(2000)
|
||||
await scheduler.wait(1010)
|
||||
|
||||
// update post once again
|
||||
post.title = "Updated Title"
|
||||
@ -120,9 +120,9 @@ describe("column kinds > update date column", () => {
|
||||
await postRepository.findOneByOrFail({
|
||||
id: post.id,
|
||||
})
|
||||
expect(loadedPostAfterUpdate.updatedAt.getTime()).to.be.not.eql(
|
||||
loadedPostBeforeUpdate.updatedAt.getTime(),
|
||||
)
|
||||
expect(
|
||||
loadedPostAfterUpdate.updatedAt.getTime(),
|
||||
).to.be.greaterThan(loadedPostBeforeUpdate.updatedAt.getTime())
|
||||
}),
|
||||
))
|
||||
|
||||
@ -5,7 +5,6 @@ import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
sleep,
|
||||
} from "../../../utils/test-utils"
|
||||
import { Post } from "./entity/Post"
|
||||
|
||||
@ -98,9 +97,6 @@ describe("column kinds > version column", () => {
|
||||
post.title = "Post"
|
||||
await postRepository.save(post)
|
||||
|
||||
// wait a second
|
||||
await sleep(1000)
|
||||
|
||||
// update post once again
|
||||
post.title = "Updated Title"
|
||||
await postRepository.save(post)
|
||||
@ -1,15 +1,15 @@
|
||||
import "reflect-metadata"
|
||||
import { expect } from "chai"
|
||||
import "reflect-metadata"
|
||||
import { scheduler } from "timers/promises"
|
||||
import { DataSource } from "../../../src/data-source/DataSource"
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
sleep,
|
||||
} from "../../utils/test-utils"
|
||||
import { DataSource } from "../../../src/data-source/DataSource"
|
||||
import { Address } from "./entity/Address"
|
||||
import { User } from "./entity/User"
|
||||
import { MockQueryResultCache } from "./provider/MockQueryResultCache"
|
||||
import { Address } from "./entity/Address"
|
||||
|
||||
describe("custom cache provider", () => {
|
||||
let connections: DataSource[]
|
||||
@ -101,7 +101,7 @@ describe("custom cache provider", () => {
|
||||
expect(users3.length).to.be.equal(1)
|
||||
|
||||
// give some time for cache to expire
|
||||
await sleep(1000)
|
||||
await scheduler.wait(1010)
|
||||
|
||||
// now, when our cache has expired we check if we have new user inserted even with cache enabled
|
||||
const users4 = await connection
|
||||
@ -179,7 +179,7 @@ describe("custom cache provider", () => {
|
||||
expect(users3.length).to.be.equal(1)
|
||||
|
||||
// give some time for cache to expire
|
||||
await sleep(1000)
|
||||
await scheduler.wait(1010)
|
||||
|
||||
// now, when our cache has expired we check if we have new user inserted even with cache enabled
|
||||
const users4 = await connection
|
||||
@ -249,7 +249,7 @@ describe("custom cache provider", () => {
|
||||
expect(users2.length).to.be.equal(2)
|
||||
|
||||
// give some time for cache to expire
|
||||
await sleep(1000)
|
||||
await scheduler.wait(1010)
|
||||
|
||||
// but with cache enabled it must not return newly inserted entity since cache is not expired yet
|
||||
const users3 = await connection
|
||||
@ -263,7 +263,7 @@ describe("custom cache provider", () => {
|
||||
expect(users3.length).to.be.equal(1)
|
||||
|
||||
// give some time for cache to expire
|
||||
await sleep(1000)
|
||||
await scheduler.wait(1010)
|
||||
|
||||
// now, when our cache has expired we check if we have new user inserted even with cache enabled
|
||||
const users4 = await connection
|
||||
@ -389,7 +389,7 @@ describe("custom cache provider", () => {
|
||||
expect(users3).to.be.equal(1)
|
||||
|
||||
// give some time for cache to expire
|
||||
await sleep(1000)
|
||||
await scheduler.wait(1010)
|
||||
|
||||
// now, when our cache has expired we check if we have new user inserted even with cache enabled
|
||||
const users4 = await connection
|
||||
50
test/functional/columns/date-utc/date-utc.test.ts
Normal file
50
test/functional/columns/date-utc/date-utc.test.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import "reflect-metadata"
|
||||
import { expect } from "chai"
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
} from "../../../utils/test-utils"
|
||||
import { Event } from "./entity/Event"
|
||||
import { DataSource } from "../../../../src"
|
||||
|
||||
describe("columns > date utc flag", () => {
|
||||
let originalTZ: string | undefined
|
||||
let connections: DataSource[]
|
||||
|
||||
before(async () => {
|
||||
originalTZ = process.env.TZ
|
||||
process.env.TZ = "America/New_York"
|
||||
connections = await createTestingConnections({
|
||||
entities: [Event],
|
||||
})
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
process.env.TZ = originalTZ
|
||||
await closeTestingConnections(connections)
|
||||
})
|
||||
|
||||
beforeEach(() => reloadTestingDatabases(connections))
|
||||
|
||||
it("should save date columns in UTC when utc flag is true and in local timezone when false", () =>
|
||||
Promise.all(
|
||||
connections.map(async (connection) => {
|
||||
const event = new Event()
|
||||
const testDate = new Date(Date.UTC(2025, 5, 1)) // 2025-06-01 in UTC
|
||||
|
||||
event.localDate = testDate
|
||||
event.utcDate = testDate
|
||||
|
||||
const savedEvent = await connection.manager.save(event)
|
||||
const result = await connection.manager.findOneBy(Event, {
|
||||
id: savedEvent.id,
|
||||
})
|
||||
|
||||
// UTC flag true: should save as 2025-06-01 (UTC date)
|
||||
expect(result!.utcDate).to.equal("2025-06-01")
|
||||
// UTC flag false (default): should save as 2025-05-31 (local timezone)
|
||||
expect(result!.localDate).to.equal("2025-05-31")
|
||||
}),
|
||||
))
|
||||
})
|
||||
17
test/functional/columns/date-utc/entity/Event.ts
Normal file
17
test/functional/columns/date-utc/entity/Event.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Entity } from "../../../../../src/decorator/entity/Entity"
|
||||
import { PrimaryGeneratedColumn } from "../../../../../src/decorator/columns/PrimaryGeneratedColumn"
|
||||
import { Column } from "../../../../../src/decorator/columns/Column"
|
||||
|
||||
@Entity({
|
||||
name: "event",
|
||||
})
|
||||
export class Event {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
@Column({ type: "date" })
|
||||
localDate: Date
|
||||
|
||||
@Column({ type: "date", utc: true })
|
||||
utcDate: Date
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user