@depup/typeorm-extension 3.9.0-depup.0 → 4.1.0-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.MD +290 -134
- package/README.md +4 -6
- package/bin/cli.mjs +538 -267
- package/bin/cli.mjs.map +1 -0
- package/changes.json +3 -11
- package/dist/index.d.mts +1469 -0
- package/dist/index.mjs +3103 -2981
- package/dist/index.mjs.map +1 -1
- package/package.json +50 -56
- package/bin/cli.cjs +0 -275
- package/dist/cli/commands/database/create.d.ts +0 -27
- package/dist/cli/commands/database/drop.d.ts +0 -23
- package/dist/cli/commands/database/index.d.ts +0 -2
- package/dist/cli/commands/index.d.ts +0 -2
- package/dist/cli/commands/seed/create.d.ts +0 -21
- package/dist/cli/commands/seed/index.d.ts +0 -2
- package/dist/cli/commands/seed/run.d.ts +0 -24
- package/dist/cli/index.d.ts +0 -2
- package/dist/data-source/find/index.d.ts +0 -2
- package/dist/data-source/find/module.d.ts +0 -3
- package/dist/data-source/find/type.d.ts +0 -22
- package/dist/data-source/index.d.ts +0 -4
- package/dist/data-source/options/index.d.ts +0 -4
- package/dist/data-source/options/module.d.ts +0 -8
- package/dist/data-source/options/singleton.d.ts +0 -4
- package/dist/data-source/options/type.d.ts +0 -26
- package/dist/data-source/options/utils/env.d.ts +0 -4
- package/dist/data-source/options/utils/index.d.ts +0 -2
- package/dist/data-source/options/utils/merge.d.ts +0 -2
- package/dist/data-source/singleton.d.ts +0 -5
- package/dist/data-source/type.d.ts +0 -2
- package/dist/database/driver/cockroachdb.d.ts +0 -4
- package/dist/database/driver/index.d.ts +0 -9
- package/dist/database/driver/mongodb.d.ts +0 -6
- package/dist/database/driver/mssql.d.ts +0 -6
- package/dist/database/driver/mysql.d.ts +0 -7
- package/dist/database/driver/oracle.d.ts +0 -6
- package/dist/database/driver/postgres.d.ts +0 -8
- package/dist/database/driver/sqlite.d.ts +0 -3
- package/dist/database/driver/types.d.ts +0 -20
- package/dist/database/driver/utils/build.d.ts +0 -3
- package/dist/database/driver/utils/character-set.d.ts +0 -2
- package/dist/database/driver/utils/charset.d.ts +0 -2
- package/dist/database/driver/utils/create.d.ts +0 -2
- package/dist/database/driver/utils/index.d.ts +0 -4
- package/dist/database/index.d.ts +0 -3
- package/dist/database/methods/check/index.d.ts +0 -2
- package/dist/database/methods/check/module.d.ts +0 -7
- package/dist/database/methods/check/types.d.ts +0 -51
- package/dist/database/methods/create/index.d.ts +0 -1
- package/dist/database/methods/create/module.d.ts +0 -10
- package/dist/database/methods/drop/index.d.ts +0 -1
- package/dist/database/methods/drop/module.d.ts +0 -10
- package/dist/database/methods/index.d.ts +0 -4
- package/dist/database/methods/type.d.ts +0 -43
- package/dist/database/utils/context.d.ts +0 -3
- package/dist/database/utils/index.d.ts +0 -5
- package/dist/database/utils/migration.d.ts +0 -2
- package/dist/database/utils/query.d.ts +0 -3
- package/dist/database/utils/schema.d.ts +0 -3
- package/dist/database/utils/type.d.ts +0 -32
- package/dist/env/constants.d.ts +0 -68
- package/dist/env/index.d.ts +0 -3
- package/dist/env/module.d.ts +0 -4
- package/dist/env/type.d.ts +0 -36
- package/dist/env/utils.d.ts +0 -3
- package/dist/errors/base.d.ts +0 -2
- package/dist/errors/driver.d.ts +0 -6
- package/dist/errors/index.d.ts +0 -3
- package/dist/errors/options.d.ts +0 -7
- package/dist/helpers/entity/error.d.ts +0 -20
- package/dist/helpers/entity/index.d.ts +0 -5
- package/dist/helpers/entity/join-columns.d.ts +0 -16
- package/dist/helpers/entity/metadata.d.ts +0 -10
- package/dist/helpers/entity/property-names.d.ts +0 -11
- package/dist/helpers/entity/uniqueness.d.ts +0 -28
- package/dist/helpers/index.d.ts +0 -1
- package/dist/index.cjs +0 -3258
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/query/index.d.ts +0 -4
- package/dist/query/module.d.ts +0 -5
- package/dist/query/parameter/fields/index.d.ts +0 -2
- package/dist/query/parameter/fields/module.d.ts +0 -25
- package/dist/query/parameter/fields/type.d.ts +0 -6
- package/dist/query/parameter/filters/index.d.ts +0 -2
- package/dist/query/parameter/filters/module.d.ts +0 -35
- package/dist/query/parameter/filters/type.d.ts +0 -12
- package/dist/query/parameter/index.d.ts +0 -5
- package/dist/query/parameter/pagination/index.d.ts +0 -2
- package/dist/query/parameter/pagination/module.d.ts +0 -26
- package/dist/query/parameter/pagination/type.d.ts +0 -3
- package/dist/query/parameter/relations/index.d.ts +0 -2
- package/dist/query/parameter/relations/module.d.ts +0 -27
- package/dist/query/parameter/relations/type.d.ts +0 -8
- package/dist/query/parameter/sort/index.d.ts +0 -2
- package/dist/query/parameter/sort/module.d.ts +0 -26
- package/dist/query/parameter/sort/type.d.ts +0 -6
- package/dist/query/type.d.ts +0 -16
- package/dist/query/utils/alias.d.ts +0 -2
- package/dist/query/utils/index.d.ts +0 -3
- package/dist/query/utils/key.d.ts +0 -1
- package/dist/query/utils/option.d.ts +0 -1
- package/dist/seeder/entity.d.ts +0 -42
- package/dist/seeder/executor.d.ts +0 -24
- package/dist/seeder/factory/index.d.ts +0 -4
- package/dist/seeder/factory/manager.d.ts +0 -8
- package/dist/seeder/factory/module.d.ts +0 -17
- package/dist/seeder/factory/type.d.ts +0 -12
- package/dist/seeder/factory/utils.d.ts +0 -7
- package/dist/seeder/index.d.ts +0 -6
- package/dist/seeder/module.d.ts +0 -5
- package/dist/seeder/type.d.ts +0 -44
- package/dist/seeder/utils/file-path.d.ts +0 -7
- package/dist/seeder/utils/index.d.ts +0 -3
- package/dist/seeder/utils/prepare.d.ts +0 -2
- package/dist/seeder/utils/template.d.ts +0 -1
- package/dist/utils/code-transformation/constants.d.ts +0 -4
- package/dist/utils/code-transformation/index.d.ts +0 -2
- package/dist/utils/code-transformation/module.d.ts +0 -3
- package/dist/utils/entity.d.ts +0 -2
- package/dist/utils/file-path.d.ts +0 -9
- package/dist/utils/file-system.d.ts +0 -1
- package/dist/utils/has-property.d.ts +0 -2
- package/dist/utils/index.d.ts +0 -10
- package/dist/utils/object.d.ts +0 -2
- package/dist/utils/promise.d.ts +0 -1
- package/dist/utils/separator.d.ts +0 -3
- package/dist/utils/slash.d.ts +0 -2
- package/dist/utils/tsconfig/index.d.ts +0 -2
- package/dist/utils/tsconfig/module.d.ts +0 -2
- package/dist/utils/tsconfig/type.d.ts +0 -13
package/README.MD
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src=".github/assets/logo.svg" alt="typeorm-extension" width="120">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
<h1 align="center">typeorm-extension</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://badge.fury.io/js/typeorm-extension"><img src="https://badge.fury.io/js/typeorm-extension.svg" alt="npm version"></a>
|
|
9
|
+
<a href="https://codecov.io/gh/Tada5hi/typeorm-extension"><img src="https://codecov.io/gh/Tada5hi/typeorm-extension/branch/master/graph/badge.svg?token=4KNSG8L13V" alt="codecov"></a>
|
|
10
|
+
<a href="https://github.com/Tada5hi/typeorm-extension"><img src="https://github.com/Tada5hi/typeorm-extension/workflows/CI/badge.svg" alt="Master Workflow"></a>
|
|
11
|
+
<a href="https://snyk.io/test/github/Tada5hi/typeorm-extension?targetFile=package.json"><img src="https://snyk.io/test/github/Tada5hi/typeorm-extension/badge.svg?targetFile=package.json" alt="Known Vulnerabilities"></a>
|
|
12
|
+
<a href="https://conventionalcommits.org"><img src="https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?logo=conventionalcommits&logoColor=white" alt="Conventional Commits"></a>
|
|
13
|
+
</p>
|
|
8
14
|
|
|
9
15
|
This is a library to
|
|
10
16
|
- `create`, `drop` & `seed` the (default-) database 🔥
|
|
11
17
|
- manage one or many data-source instances 👻
|
|
12
|
-
- parse & apply query parameters (extended **JSON:API** specification & fully typed) to:
|
|
13
|
-
- `filter` (related) resources according to one or more criteria,
|
|
14
|
-
- reduce (related) resource `fields`,
|
|
15
|
-
- `include` related resources,
|
|
16
|
-
- `sort` resources according to one or more criteria,
|
|
17
|
-
- limit the number of resources returned in a response by `page` limit & offset
|
|
18
|
-
|
|
19
|
-
> **Warning**
|
|
20
|
-
> This readme includes the documentation for the upcoming version 3.
|
|
21
|
-
> This is the [link](https://github.com/tada5hi/typeorm-extension/tree/v2) for the v2.
|
|
22
18
|
|
|
23
19
|
**Table of Contents**
|
|
24
20
|
- [Installation](#installation)
|
|
@@ -30,6 +26,9 @@ This is a library to
|
|
|
30
26
|
- [Database](#database)
|
|
31
27
|
- [Create](#create)
|
|
32
28
|
- [Drop](#drop)
|
|
29
|
+
- [Schema Drift](#schema-drift)
|
|
30
|
+
- [Generate Migration](#generate-migration)
|
|
31
|
+
- [Repair Migrations](#repair-migrations)
|
|
33
32
|
- [Instances](#instances)
|
|
34
33
|
- [Single](#single)
|
|
35
34
|
- [Multiple](#multiple)
|
|
@@ -46,9 +45,13 @@ This is a library to
|
|
|
46
45
|
## Installation
|
|
47
46
|
|
|
48
47
|
```bash
|
|
49
|
-
npm install typeorm-extension --save
|
|
48
|
+
npm install typeorm-extension typeorm --save
|
|
50
49
|
```
|
|
51
50
|
|
|
51
|
+
`typeorm` is a peer dependency and is required in the range `^1.1.0`. Seeder factories generate their data
|
|
52
|
+
with a library of your choice, so nothing else is required. The examples below use
|
|
53
|
+
[faker](https://fakerjs.dev/guide/) (`npm install @faker-js/faker`).
|
|
54
|
+
|
|
52
55
|
## Documentation
|
|
53
56
|
|
|
54
57
|
To read the docs, visit [https://typeorm-extension.tada5hi.net](https://typeorm-extension.tada5hi.net)
|
|
@@ -57,64 +60,74 @@ To read the docs, visit [https://typeorm-extension.tada5hi.net](https://typeorm-
|
|
|
57
60
|
|
|
58
61
|
### CLI
|
|
59
62
|
|
|
60
|
-
If you use esm, the executable must be changed from `typeorm-extension` to `typeorm-extension-esm`.
|
|
61
63
|
The following commands are available in the terminal:
|
|
62
|
-
- `typeorm-extension db
|
|
63
|
-
- `typeorm-extension db
|
|
64
|
-
- `typeorm-extension
|
|
65
|
-
- `typeorm-extension seed
|
|
64
|
+
- `typeorm-extension db create` to create the database
|
|
65
|
+
- `typeorm-extension db drop` to drop the database
|
|
66
|
+
- `typeorm-extension db drift` to assert that the database schema matches the entity metadata
|
|
67
|
+
- `typeorm-extension seed run` to seed the database
|
|
68
|
+
- `typeorm-extension seed create` to create a new seeder
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
The legacy colon-form (`db:create`, `db:drop`, `seed:run`, `seed:create`) is still accepted for backwards compatibility.
|
|
71
|
+
|
|
72
|
+
If the application has not yet been built and you want to run the CLI against TypeScript sources directly, invoke the ESM bundle with a TypeScript-aware Node loader (e.g. `tsx` or Node's `--experimental-strip-types`):
|
|
68
73
|
|
|
69
74
|
```
|
|
70
75
|
"scripts": {
|
|
71
|
-
"db:create":
|
|
72
|
-
"db:drop":
|
|
73
|
-
"
|
|
74
|
-
"seed:
|
|
76
|
+
"db:create": "tsx ./node_modules/typeorm-extension/bin/cli.mjs db create",
|
|
77
|
+
"db:drop": "tsx ./node_modules/typeorm-extension/bin/cli.mjs db drop",
|
|
78
|
+
"db:drift": "tsx ./node_modules/typeorm-extension/bin/cli.mjs db drift",
|
|
79
|
+
"seed:run": "tsx ./node_modules/typeorm-extension/bin/cli.mjs seed run",
|
|
80
|
+
"seed:create": "tsx ./node_modules/typeorm-extension/bin/cli.mjs seed create"
|
|
75
81
|
}
|
|
76
82
|
```
|
|
77
|
-
To test the application in the context of an esm project, the following adjustments must be made:
|
|
78
|
-
- executable `ts-node` to `ts-node-esm`
|
|
79
|
-
- library path `cli.cjs` to `cli.mjs`
|
|
80
83
|
|
|
81
84
|
Read the [Seeding Configuration](#configuration) section to find out how to specify the path,
|
|
82
85
|
for the seeder- & factory-location.
|
|
83
86
|
|
|
84
87
|
#### CLI Options
|
|
85
88
|
|
|
86
|
-
| Option | Commands
|
|
87
|
-
|
|
88
|
-
| `--root` or `-r` | `db
|
|
89
|
-
| `--
|
|
90
|
-
| `--
|
|
91
|
-
| `--
|
|
92
|
-
| `--
|
|
93
|
-
| `--
|
|
89
|
+
| Option | Commands | Default | Description |
|
|
90
|
+
|-------------------------|---------------------------------------------------|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
91
|
+
| `--root` or `-r` | `db create`, `db drift`, `db drop`, `seed create`, `seed run` | `process.cwd()` | Root directory of the project. |
|
|
92
|
+
| `--tsconfig` or `-tc` | `db create`, `db drift`, `db drop`, `seed run` | `tsconfig.json` | Name (or relative path incl. name) of the tsconfig file. |
|
|
93
|
+
| `--dataSource` or `-d` | `db create`, `db drift`, `db drop`, `seed run` | `data-source` | Name (or relative path incl. name) of the data-source file. |
|
|
94
|
+
| `--synchronize` or `-s` | `db create` | `yes` | Synchronize the database schema after database creation. Options: `yes` or `no`. |
|
|
95
|
+
| `--initialDatabase` | `db create` | `undefined` | Specify the initial database to connect to. This option is only relevant for the `postgres` driver, which must always connect to a database. If no database is provided, the database name will be equal to the connection user name. |
|
|
96
|
+
| `--skipWithoutMigrations` | `db drift` | `false` | Report no drift if the data-source has no migrations registered. |
|
|
97
|
+
| `--name` or `-n` | `seed create` (required), `seed run` (optional) | `undefined` | Name (or relative path incl. name) of the seeder. Required on `seed create`; on `seed run` restricts execution to the matching seeder. |
|
|
98
|
+
| `--timestamp` or `-t` | `seed create` | `Date.now()` | Custom timestamp used in the generated seeder filename. |
|
|
99
|
+
| `--javascript` or `-j` | `seed create` | `false` | Generate a seeder file for JavaScript instead of TypeScript. |
|
|
100
|
+
| `--preserveFilePaths` | `db create`, `db drift`, `db drop`, `seed run` | `false` | This option indicates if file paths should be preserved and treated as if the just-in-time compilation environment is detected. |
|
|
101
|
+
| `--log-level` | `db create`, `db drift`, `db drop`, `seed create`, `seed run` | `info` | Logger verbosity. One of `silent`, `info`, `debug`. |
|
|
94
102
|
|
|
95
103
|
#### CLI Examples
|
|
96
104
|
**`Database Create`**
|
|
97
105
|
```shell
|
|
98
|
-
|
|
106
|
+
tsx ./node_modules/typeorm-extension/bin/cli.mjs db create -d src/data-source.ts
|
|
99
107
|
```
|
|
100
108
|
**`Database Drop`**
|
|
101
109
|
```shell
|
|
102
|
-
|
|
110
|
+
tsx ./node_modules/typeorm-extension/bin/cli.mjs db drop -d src/data-source.ts
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**`Database Drift`**
|
|
114
|
+
```shell
|
|
115
|
+
tsx ./node_modules/typeorm-extension/bin/cli.mjs db drift -d src/data-source.ts
|
|
103
116
|
```
|
|
104
117
|
|
|
105
118
|
**`Seed Run`**
|
|
106
119
|
```shell
|
|
107
|
-
|
|
120
|
+
tsx ./node_modules/typeorm-extension/bin/cli.mjs seed run -d src/data-source.ts
|
|
108
121
|
```
|
|
109
122
|
|
|
110
123
|
**`Seed Run Explicit`**
|
|
111
124
|
```shell
|
|
112
|
-
|
|
125
|
+
tsx ./node_modules/typeorm-extension/bin/cli.mjs seed run -d src/data-source.ts --name src/database/seeds/user.ts
|
|
113
126
|
```
|
|
114
127
|
|
|
115
128
|
**`Seed Create`**
|
|
116
129
|
```shell
|
|
117
|
-
|
|
130
|
+
tsx ./node_modules/typeorm-extension/bin/cli.mjs seed create --name src/database/seeds/user.ts
|
|
118
131
|
```
|
|
119
132
|
|
|
120
133
|
### Database
|
|
@@ -129,7 +142,7 @@ import { createDatabase } from 'typeorm-extension';
|
|
|
129
142
|
|
|
130
143
|
(async () => {
|
|
131
144
|
const options: DataSourceOptions = {
|
|
132
|
-
type: 'better-
|
|
145
|
+
type: 'better-sqlite3',
|
|
133
146
|
database: 'db.sqlite'
|
|
134
147
|
};
|
|
135
148
|
|
|
@@ -201,7 +214,7 @@ import { dropDatabase } from 'typeorm-extension';
|
|
|
201
214
|
|
|
202
215
|
(async () => {
|
|
203
216
|
const options: DataSourceOptions = {
|
|
204
|
-
type: 'better-
|
|
217
|
+
type: 'better-sqlite3',
|
|
205
218
|
database: 'db.sqlite'
|
|
206
219
|
};
|
|
207
220
|
|
|
@@ -252,6 +265,99 @@ To get a better overview and understanding of the
|
|
|
252
265
|
[dropDatabase](https://typeorm-extension.tada5hi.net/guide/database-api-reference.html#dropDatabase)
|
|
253
266
|
function, check out the documentation.
|
|
254
267
|
|
|
268
|
+
#### Schema Drift
|
|
269
|
+
|
|
270
|
+
Compare the database schema against the entity metadata and get back the statements which would reconcile them.
|
|
271
|
+
|
|
272
|
+
Run it right after the migrations to close the blind spot of a project which builds its schema with migrations in
|
|
273
|
+
production but with `synchronize()` in tests: the two descriptions can drift apart silently, and it only surfaces
|
|
274
|
+
when the next generated migration reconciles them.
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
import { assertSchemaMatchesMetadata, getSchemaDrift } from 'typeorm-extension';
|
|
278
|
+
|
|
279
|
+
(async () => {
|
|
280
|
+
const drift = await getSchemaDrift(dataSource);
|
|
281
|
+
if (drift.exists) {
|
|
282
|
+
console.log(drift.up.map((statement) => statement.query));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// ... or let it throw a SchemaDriftError listing the statements
|
|
286
|
+
await assertSchemaMatchesMetadata(dataSource);
|
|
287
|
+
})();
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
The same check is available on the command line as `typeorm-extension db drift`, which exits with code `1` on drift.
|
|
291
|
+
|
|
292
|
+
#### Generate Migration
|
|
293
|
+
|
|
294
|
+
`generateMigration` writes a migration file from the same schema comparison, using typeorm's own statements and file
|
|
295
|
+
templates. The data source must already be initialized.
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
import { generateMigration } from 'typeorm-extension';
|
|
299
|
+
|
|
300
|
+
(async () => {
|
|
301
|
+
await generateMigration({
|
|
302
|
+
dataSource,
|
|
303
|
+
name: 'add-role',
|
|
304
|
+
directoryPath: 'src/migrations',
|
|
305
|
+
});
|
|
306
|
+
})();
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
The file is written as `<timestamp>-<name>.<language>`, by default into `migrations/`. Set `language: 'js'` (plus
|
|
310
|
+
`esm: true` for `export class` syntax) for a JavaScript migration, or `preview: true` to receive the statements without
|
|
311
|
+
writing a file.
|
|
312
|
+
|
|
313
|
+
#### Repair Migrations
|
|
314
|
+
|
|
315
|
+
Renaming a constraint is dialect-asymmetric and easy to get wrong. These helpers read the current state back from the
|
|
316
|
+
database, apply the change only if it is still pending, and return whether they did something. That way a repair migration
|
|
317
|
+
stays resumable (mysql commits DDL regardless of the surrounding transaction) and safe to run against a database which
|
|
318
|
+
never had the drift.
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
import type { MigrationInterface, QueryRunner } from 'typeorm';
|
|
322
|
+
import { changeColumnType, renameForeignKey, renameIndex } from 'typeorm-extension';
|
|
323
|
+
|
|
324
|
+
export class RepairSchema1700000000000 implements MigrationInterface {
|
|
325
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
326
|
+
await renameIndex(queryRunner, {
|
|
327
|
+
table: 'auth_events',
|
|
328
|
+
from: 'IDX_auth_events_actor_name',
|
|
329
|
+
to: 'IDX_9f6d1a2b3c4d5e6f70819293',
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
await renameForeignKey(queryRunner, {
|
|
333
|
+
table: 'auth_permissions',
|
|
334
|
+
from: 'FK_auth_permissions_client',
|
|
335
|
+
to: 'FK_1a2b3c4d5e6f708192a3b4c5',
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
await changeColumnType(queryRunner, {
|
|
339
|
+
table: 'auth_permissions',
|
|
340
|
+
column: 'client_id',
|
|
341
|
+
from: { type: 'varchar', length: 36 },
|
|
342
|
+
to: { type: 'varchar', length: 255 },
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
`renameIndex` and `renameForeignKey` support `postgres`, `cockroachdb`, `mysql` and `mariadb` and throw a `DriverError`
|
|
349
|
+
on any other driver. `changeColumnType` and `withForeignKeyChecksDisabled` work everywhere: `changeColumnType` alters
|
|
350
|
+
the column in place (keeping its values) on every relational driver but sqlite, which typeorm handles safely by
|
|
351
|
+
recreating the table.
|
|
352
|
+
|
|
353
|
+
Each helper returns `false` when the change is already applied, which keeps a repair migration resumable. If the
|
|
354
|
+
database is in **neither** the expected nor the desired state it raises a `SchemaAlterationError` instead of returning
|
|
355
|
+
quietly, since a repair migration which repairs nothing would otherwise pass for a successful one. Pass
|
|
356
|
+
`strict: false` per call to opt out.
|
|
357
|
+
|
|
358
|
+
To get a better overview and understanding of these functions, check out the
|
|
359
|
+
[documentation](https://typeorm-extension.tada5hi.net/guide/database-api-reference.html).
|
|
360
|
+
|
|
255
361
|
### Instances
|
|
256
362
|
|
|
257
363
|
#### Single
|
|
@@ -311,7 +417,7 @@ Seeding the database is fairly easy and can be achieved by following the steps b
|
|
|
311
417
|
|
|
312
418
|
Seeder paths are configured as **glob patterns**, making it easy
|
|
313
419
|
to match all the factory/seeder files in your project without configuration effort:
|
|
314
|
-
- use `*` to match anything
|
|
420
|
+
- use `*` to match anything except slashes and hidden files
|
|
315
421
|
- use `**` to match zero or more directories
|
|
316
422
|
- use comma separate values between `{}` to match against a list of options
|
|
317
423
|
|
|
@@ -330,8 +436,14 @@ The following values are assumed by default:
|
|
|
330
436
|
|
|
331
437
|
Note: When seeder paths are configured as **glob patterns**, the paths are resolved and sorted in alphabetical order using filenames. This helps to ensure that the seeders are executed in the correct order.
|
|
332
438
|
|
|
439
|
+
Seeder options can be provided per invocation (`runSeeder(s)` options parameter), on the extended
|
|
440
|
+
data-source options, or via environment variables. Explicit input wins over the data-source options,
|
|
441
|
+
which win over the environment; built-in defaults apply last.
|
|
442
|
+
|
|
333
443
|
It is possible to define that a seeder is only executed once.
|
|
334
|
-
This can either be set globally using the
|
|
444
|
+
This can either be set globally using the `seedTracking` option or locally using the `track` property of a seeder class.
|
|
445
|
+
Executed seeds are recorded in a `seeds` table (a collection for MongoDB);
|
|
446
|
+
the table name can be changed with the `seedTableName` option.
|
|
335
447
|
|
|
336
448
|
`data-source.ts`
|
|
337
449
|
|
|
@@ -340,7 +452,7 @@ import { DataSource, DataSourceOptions } from 'typeorm';
|
|
|
340
452
|
import { SeederOptions } from 'typeorm-extension';
|
|
341
453
|
|
|
342
454
|
const options: DataSourceOptions & SeederOptions = {
|
|
343
|
-
type: 'better-
|
|
455
|
+
type: 'better-sqlite3',
|
|
344
456
|
database: 'db.sqlite',
|
|
345
457
|
|
|
346
458
|
seeds: ['src/database/seeds/**/*{.ts,.js}'],
|
|
@@ -359,7 +471,7 @@ import { runSeeders, SeederOptions } from 'typeorm-extension';
|
|
|
359
471
|
|
|
360
472
|
(async () => {
|
|
361
473
|
const options: DataSourceOptions = {
|
|
362
|
-
type: 'better-
|
|
474
|
+
type: 'better-sqlite3',
|
|
363
475
|
database: 'db.sqlite',
|
|
364
476
|
};
|
|
365
477
|
|
|
@@ -404,27 +516,32 @@ export class User {
|
|
|
404
516
|
To create entities with random data, create a factory for each desired entity.
|
|
405
517
|
The definition of a factory is **optional**.
|
|
406
518
|
|
|
407
|
-
The factory callback
|
|
408
|
-
|
|
519
|
+
The factory callback returns the entity to persist. Pick any data generator you like and import it in the
|
|
520
|
+
factory file. The examples use [faker](https://fakerjs.dev/guide/) (`npm install @faker-js/faker`).
|
|
409
521
|
|
|
410
522
|
**`user.factory.ts`**
|
|
411
523
|
```typescript
|
|
524
|
+
import { faker } from '@faker-js/faker';
|
|
412
525
|
import { setSeederFactory } from 'typeorm-extension';
|
|
413
526
|
import { User } from './user';
|
|
414
527
|
|
|
415
|
-
export default setSeederFactory(User, (
|
|
528
|
+
export default setSeederFactory(User, () => {
|
|
416
529
|
const user = new User();
|
|
417
|
-
user.firstName = faker.
|
|
418
|
-
user.lastName = faker.
|
|
419
|
-
user.email = faker.internet.email(user.firstName, user.lastName);
|
|
530
|
+
user.firstName = faker.person.firstName('male');
|
|
531
|
+
user.lastName = faker.person.lastName('male');
|
|
532
|
+
user.email = faker.internet.email({ firstName: user.firstName, lastName: user.lastName });
|
|
420
533
|
|
|
421
534
|
return user;
|
|
422
535
|
})
|
|
423
536
|
```
|
|
424
537
|
|
|
538
|
+
Since the generator instance belongs to the factory file, locales and reproducible runs are configured
|
|
539
|
+
through the generator's own API, for example `import { fakerDE as faker } from '@faker-js/faker'`
|
|
540
|
+
or `faker.seed(1234)`.
|
|
541
|
+
|
|
425
542
|
#### Seed
|
|
426
|
-
And last but not least, create a seeder. The seeder can be called by the cli command `seed` or in the codebase
|
|
427
|
-
by using the function `runSeeder`.
|
|
543
|
+
And last but not least, create a seeder. The seeder can be called by the cli command `seed:run` or in the codebase
|
|
544
|
+
by using the function `runSeeder` / `runSeeders`.
|
|
428
545
|
A seeder class only requires one method, called `run` and provides the arguments `dataSource` & `factoryManager`.
|
|
429
546
|
|
|
430
547
|
**`user.seeder.ts`**
|
|
@@ -469,6 +586,10 @@ export default class UserSeeder implements Seeder {
|
|
|
469
586
|
}
|
|
470
587
|
```
|
|
471
588
|
|
|
589
|
+
Factories obtained through the `factoryManager` argument are bound to the data source of the
|
|
590
|
+
current seeder run, so `save()` and `saveMany()` persist there. A factory used outside a seeder
|
|
591
|
+
run falls back to the data source registered for the `default` alias.
|
|
592
|
+
|
|
472
593
|
#### Execute
|
|
473
594
|
|
|
474
595
|
Populate the database from the code base:
|
|
@@ -476,11 +597,11 @@ Populate the database from the code base:
|
|
|
476
597
|
```typescript
|
|
477
598
|
import { DataSource, DataSourceOptions } from 'typeorm';
|
|
478
599
|
import { runSeeders, SeederOptions } from 'typeorm-extension';
|
|
479
|
-
import { User } from 'user';
|
|
600
|
+
import { User } from './user';
|
|
480
601
|
|
|
481
602
|
(async () => {
|
|
482
603
|
const options: DataSourceOptions & SeederOptions = {
|
|
483
|
-
type: 'better-
|
|
604
|
+
type: 'better-sqlite3',
|
|
484
605
|
database: 'db.sqlite',
|
|
485
606
|
entities: [User],
|
|
486
607
|
|
|
@@ -500,13 +621,13 @@ Populate the database by explicit definitions from the codebase.
|
|
|
500
621
|
```typescript
|
|
501
622
|
import { DataSource, DataSourceOptions } from 'typeorm';
|
|
502
623
|
import { runSeeders, SeederOptions } from 'typeorm-extension';
|
|
503
|
-
import { User } from 'user';
|
|
504
|
-
import UserSeeder from 'user.seeder';
|
|
505
|
-
import UserFactory from 'user.factory';
|
|
624
|
+
import { User } from './user';
|
|
625
|
+
import UserSeeder from './user.seeder';
|
|
626
|
+
import UserFactory from './user.factory';
|
|
506
627
|
|
|
507
628
|
(async () => {
|
|
508
629
|
const options: DataSourceOptions & SeederOptions = {
|
|
509
|
-
type: 'better-
|
|
630
|
+
type: 'better-sqlite3',
|
|
510
631
|
database: 'db.sqlite',
|
|
511
632
|
entities: [User],
|
|
512
633
|
|
|
@@ -522,20 +643,31 @@ import UserFactory from 'user.factory';
|
|
|
522
643
|
```
|
|
523
644
|
|
|
524
645
|
### Query
|
|
525
|
-
The query submodule enables query parameter (fields, filter, ...) values to be build, parsed & validated.
|
|
526
|
-
Therefore, the [rapiq](https://www.npmjs.com/package/rapiq) library is used under the hood.
|
|
527
646
|
|
|
528
|
-
The query
|
|
529
|
-
|
|
647
|
+
The query submodule (`applyQuery`, `applyFilters`, ...) was removed in v4.
|
|
648
|
+
Its successor is [@rapiq/adapter-typeorm](https://github.com/tada5hi/rapiq/tree/master/packages/adapter-typeorm), the dedicated
|
|
649
|
+
TypeORM adapter of the [rapiq](https://github.com/tada5hi/rapiq) v2 monorepo. The query pipeline is now fully
|
|
650
|
+
**self-contained** in rapiq: decoding the raw URL query string (`@rapiq/codec-url`), typed schema
|
|
651
|
+
validation (`@rapiq/core`) and application onto the `SelectQueryBuilder` (`@rapiq/adapter-typeorm`).
|
|
652
|
+
`typeorm-extension` is no longer involved. On top of the full `applyQuery` use case it adds typed
|
|
653
|
+
schemas, nested `and` / `or` filter compounds, the `contains` operator family and collision-free join aliases.
|
|
654
|
+
|
|
655
|
+
The [monorepo](https://github.com/tada5hi/rapiq) hosts more than the TypeORM adapter: adapters for
|
|
656
|
+
drizzle, prisma, raw SQL and in-memory collections, plus pluggable input parsers (e.g. a MongoDB-style
|
|
657
|
+
filter parser and an expression parser). If rapiq is useful to you, consider giving the repo a ⭐ on GitHub.
|
|
658
|
+
|
|
659
|
+
```bash
|
|
660
|
+
npm install @rapiq/core @rapiq/codec-url @rapiq/adapter-typeorm --save
|
|
661
|
+
```
|
|
530
662
|
|
|
531
|
-
For
|
|
532
|
-
two simple entities with a relation between them are declared to demonstrate the usage of the query utils:
|
|
663
|
+
For demonstration purposes, two simple entities with a relation between them are used:
|
|
533
664
|
|
|
534
665
|
```typescript
|
|
535
666
|
import {
|
|
536
667
|
Entity,
|
|
537
668
|
PrimaryGeneratedColumn,
|
|
538
669
|
Column,
|
|
670
|
+
Index,
|
|
539
671
|
OneToOne,
|
|
540
672
|
JoinColumn
|
|
541
673
|
} from 'typeorm';
|
|
@@ -573,94 +705,118 @@ export class Profile {
|
|
|
573
705
|
}
|
|
574
706
|
```
|
|
575
707
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
but there is also a guide available for [express](https://typeorm-extension.tada5hi.net/guide/query.html).
|
|
708
|
+
Instead of passing loose options per call (as `applyQuery` did), the allowed query features are declared
|
|
709
|
+
once as a typed **schema** and registered alongside a codec:
|
|
579
710
|
|
|
580
711
|
```typescript
|
|
581
|
-
import {
|
|
582
|
-
import
|
|
583
|
-
import {
|
|
584
|
-
|
|
712
|
+
import { SchemaRegistry, defineSchema } from '@rapiq/core';
|
|
713
|
+
import { createURLCodec } from '@rapiq/codec-url';
|
|
714
|
+
import { Profile, User } from './entities';
|
|
715
|
+
|
|
716
|
+
const registry = new SchemaRegistry();
|
|
717
|
+
|
|
718
|
+
registry.add(defineSchema<Profile>({
|
|
719
|
+
name: 'profile',
|
|
720
|
+
fields: { allowed: ['id', 'avatar'] },
|
|
721
|
+
filters: { allowed: ['id'] },
|
|
722
|
+
}));
|
|
723
|
+
|
|
724
|
+
registry.add(defineSchema<User>({
|
|
725
|
+
name: 'user',
|
|
726
|
+
fields: {
|
|
727
|
+
allowed: ['id', 'name', 'email'],
|
|
728
|
+
default: ['id', 'name'],
|
|
729
|
+
},
|
|
730
|
+
filters: { allowed: ['id', 'name', 'profile.id'] },
|
|
731
|
+
relations: { allowed: ['profile'] },
|
|
732
|
+
sort: { allowed: ['id', 'name'], default: { id: 'DESC' } },
|
|
733
|
+
pagination: { maxLimit: 20 },
|
|
734
|
+
schemaMapping: { profile: 'profile' },
|
|
735
|
+
}));
|
|
736
|
+
|
|
737
|
+
export const codec = createURLCodec(registry);
|
|
738
|
+
```
|
|
585
739
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
740
|
+
The codec owns both directions. A client builds the query string with `encode`, from a typed query
|
|
741
|
+
instead of string concatenation (no registry needed on the client):
|
|
742
|
+
|
|
743
|
+
```typescript
|
|
744
|
+
import { defineQuery } from '@rapiq/core';
|
|
745
|
+
import { createURLCodec } from '@rapiq/codec-url';
|
|
746
|
+
import type { User } from './entities';
|
|
747
|
+
|
|
748
|
+
const codec = createURLCodec();
|
|
749
|
+
|
|
750
|
+
const query = defineQuery<User>({
|
|
751
|
+
fields: ['id', 'name'],
|
|
752
|
+
filters: { id: 1 },
|
|
753
|
+
relations: ['profile'],
|
|
754
|
+
pagination: { limit: 10, offset: 0 },
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
const response = await fetch(`/users?${codec.encode(query)}`);
|
|
758
|
+
```
|
|
590
759
|
|
|
591
|
-
|
|
592
|
-
|
|
760
|
+
The request handler then decodes the raw query parameters against the schema and lets the adapter apply
|
|
761
|
+
the result onto the query builder. It is shown here with [express](https://www.npmjs.com/package/express),
|
|
762
|
+
but the flow is framework-agnostic:
|
|
763
|
+
|
|
764
|
+
```typescript
|
|
765
|
+
import { ParseError } from '@rapiq/core';
|
|
766
|
+
import { TypeormAdapter } from '@rapiq/adapter-typeorm';
|
|
767
|
+
import { useDataSource } from 'typeorm-extension';
|
|
768
|
+
import { codec } from './codec';
|
|
769
|
+
import { User } from './entities';
|
|
593
770
|
|
|
594
771
|
/**
|
|
595
772
|
* Get many users.
|
|
596
773
|
*
|
|
597
774
|
* Request example
|
|
598
775
|
* - url: /users?page[limit]=10&page[offset]=0&include=profile&filter[id]=1&fields[user]=id,name
|
|
599
|
-
*
|
|
600
|
-
* Return Example:
|
|
601
|
-
* {
|
|
602
|
-
* data: [
|
|
603
|
-
* {id: 1, name: 'tada5hi', profile: {avatar: 'avatar.jpg', cover: 'cover.jpg'}}
|
|
604
|
-
* ],
|
|
605
|
-
* meta: {
|
|
606
|
-
* total: 1,
|
|
607
|
-
* limit: 20,
|
|
608
|
-
* offset: 0
|
|
609
|
-
* }
|
|
610
|
-
* }
|
|
611
|
-
* @param req
|
|
612
|
-
* @param res
|
|
613
776
|
*/
|
|
614
|
-
|
|
777
|
+
app.get('/users', async (req, res) => {
|
|
778
|
+
let query;
|
|
779
|
+
try {
|
|
780
|
+
query = codec.decode(req.query, { schema: 'user' });
|
|
781
|
+
} catch (e) {
|
|
782
|
+
// e.g. a malformed filter expression
|
|
783
|
+
if (e instanceof ParseError) {
|
|
784
|
+
return res.status(400).json({ error: e.message });
|
|
785
|
+
}
|
|
786
|
+
throw e;
|
|
787
|
+
}
|
|
788
|
+
if (!query) {
|
|
789
|
+
return res.status(400).json({ error: 'Invalid query input.' });
|
|
790
|
+
}
|
|
791
|
+
|
|
615
792
|
const dataSource = await useDataSource();
|
|
616
|
-
const
|
|
617
|
-
const query = repository.createQueryBuilder('user');
|
|
618
|
-
|
|
619
|
-
// -----------------------------------------------------
|
|
620
|
-
|
|
621
|
-
const { pagination } = applyQuery(query, useQuery(req), {
|
|
622
|
-
defaultAlias: 'user',
|
|
623
|
-
fields: {
|
|
624
|
-
// porfile fields can only be included,
|
|
625
|
-
// if the relation 'profile' is included.
|
|
626
|
-
allowed: ['id', 'name', 'profile.id', 'profile.avatar'],
|
|
627
|
-
},
|
|
628
|
-
filters: {
|
|
629
|
-
// porfile.id can only be used as a filter,
|
|
630
|
-
// if the relation 'profile' is included.
|
|
631
|
-
allowed: ['id', 'name', 'profile.id'],
|
|
632
|
-
},
|
|
633
|
-
pagination: {
|
|
634
|
-
// only allow to select 20 items at maximum.
|
|
635
|
-
maxLimit: 20
|
|
636
|
-
},
|
|
637
|
-
relations: {
|
|
638
|
-
allowed: ['profile']
|
|
639
|
-
},
|
|
640
|
-
sort: {
|
|
641
|
-
// profile.id can only be used as sorting key,
|
|
642
|
-
// if the relation 'profile' is included.
|
|
643
|
-
allowed: ['id', 'name', 'profile.id']
|
|
644
|
-
},
|
|
645
|
-
});
|
|
793
|
+
const queryBuilder = dataSource.getRepository(User).createQueryBuilder('user');
|
|
646
794
|
|
|
647
|
-
|
|
795
|
+
const { pagination } = new TypeormAdapter({ queryBuilder }).execute(query);
|
|
648
796
|
|
|
649
|
-
const [entities, total] = await
|
|
797
|
+
const [entities, total] = await queryBuilder.getManyAndCount();
|
|
650
798
|
|
|
651
|
-
|
|
799
|
+
res.json({
|
|
652
800
|
data: entities,
|
|
653
801
|
meta: {
|
|
654
802
|
total,
|
|
655
803
|
...pagination
|
|
656
804
|
}
|
|
657
|
-
};
|
|
805
|
+
});
|
|
658
806
|
});
|
|
659
|
-
|
|
660
|
-
const server = createServer(createNodeDispatcher(router));
|
|
661
|
-
server.listen(80);
|
|
662
807
|
```
|
|
663
808
|
|
|
809
|
+
A production-shaped version with strict schema-violation handling (`throwOnFailure`) is in the
|
|
810
|
+
[Express + TypeORM recipe](https://rapiq.tada5hi.net/guide/recipes/express-typeorm); the client side is covered by the
|
|
811
|
+
[frontend recipe](https://rapiq.tada5hi.net/guide/recipes/frontend).
|
|
812
|
+
|
|
813
|
+
To move over from the removed submodule, follow the migration guide:
|
|
814
|
+
[https://rapiq.tada5hi.net/guide/migration-typeorm-extension](https://rapiq.tada5hi.net/guide/migration-typeorm-extension)
|
|
815
|
+
|
|
816
|
+
> **Note**: This section is kept during the v4 release cycle to route former `applyQuery` users to the
|
|
817
|
+
> successor. With the next major release (v5) it will be removed from the README and docs; the
|
|
818
|
+
> [rapiq documentation](https://rapiq.tada5hi.net) is the canonical reference.
|
|
819
|
+
|
|
664
820
|
## Contributing
|
|
665
821
|
|
|
666
822
|
Before starting to work on a pull request, it is important to review the guidelines for
|
package/README.md
CHANGED
|
@@ -13,19 +13,17 @@ npm install @depup/typeorm-extension
|
|
|
13
13
|
|
|
14
14
|
| Field | Value |
|
|
15
15
|
|-------|-------|
|
|
16
|
-
| Original | [typeorm-extension](https://www.npmjs.com/package/typeorm-extension) @
|
|
17
|
-
| Processed | 2026-
|
|
16
|
+
| Original | [typeorm-extension](https://www.npmjs.com/package/typeorm-extension) @ 4.1.0 |
|
|
17
|
+
| Processed | 2026-08-23 |
|
|
18
18
|
| Smoke test | failed |
|
|
19
|
-
| Deps updated |
|
|
19
|
+
| Deps updated | 2 |
|
|
20
20
|
|
|
21
21
|
## Dependency Changes
|
|
22
22
|
|
|
23
23
|
| Dependency | From | To |
|
|
24
24
|
|------------|------|-----|
|
|
25
|
-
| consola | ^3.4.0 | ^3.4.2 |
|
|
26
25
|
| pascal-case | ^3.1.2 | ^4.0.0 |
|
|
27
|
-
|
|
|
28
|
-
| smob | ^1.5.0 | ^1.6.1 |
|
|
26
|
+
| smob | ^1.5.0 | ^1.6.2 |
|
|
29
27
|
|
|
30
28
|
---
|
|
31
29
|
|