typeorm-test-db 1.0.1 → 1.0.3

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.en.md CHANGED
@@ -6,8 +6,8 @@ TypeORM Test DB wraps every Jest spec in an isolated database transaction. The h
6
6
 
7
7
  ## Features
8
8
 
9
- - Transaction lifecycle helper with explicit `init` and `finish` hooks.
10
- - Jest hook registration that automatically opens and rolls back transactions.
9
+ - TypeORM test database lifecycle helper with explicit `init` and `finish` hooks.
10
+ - Framework-agnostic integration by invoking the lifecycle inside your test runner hooks.
11
11
  - Compatibility with MySQL, MariaDB, PostgreSQL, SQLite, and Better SQLite 3.
12
12
  - Deterministic data factories driven by a reproducible execution seed.
13
13
  - Shared test setup that initializes one data source per worker and runs specs in parallel.
@@ -16,21 +16,46 @@ TypeORM Test DB wraps every Jest spec in an isolated database transaction. The h
16
16
 
17
17
  ## Installation
18
18
 
19
+ <details>
20
+ <summary>pnpm</summary>
21
+
22
+ ```bash
23
+ pnpm add -D typeorm-test-db
24
+ pnpm add typeorm
25
+ ```
26
+
27
+ </details>
28
+
29
+ <details>
30
+ <summary>npm</summary>
31
+
19
32
  ```bash
20
- pnpm add typeorm-test-db
21
- pnpm add typeorm # peer dependency example
33
+ npm install -D typeorm-test-db
34
+ npm install typeorm
22
35
  ```
23
36
 
37
+ </details>
38
+
39
+ <details>
40
+ <summary>Yarn</summary>
41
+
42
+ ```bash
43
+ yarn add -D typeorm-test-db
44
+ yarn add typeorm
45
+ ```
46
+
47
+ </details>
48
+
24
49
  Install TypeORM in the host project if it is not already available.
25
50
 
26
51
  ## Usage
27
52
 
28
- Create a Jest setup file that initializes the data source and registers the transactional lifecycle.
53
+ Create a Jest setup file that initializes the data source and registers the TypeORM test database lifecycle.
29
54
 
30
55
  ```typescript
31
56
  import { afterAll, afterEach, beforeAll, beforeEach } from "@jest/globals";
32
57
  import { DataSource } from "typeorm";
33
- import { registerTransactionalTestHooks } from "typeorm-test-db";
58
+ import { TypeormTestDB } from "typeorm-test-db";
34
59
 
35
60
  const dataSource = new DataSource({
36
61
  type: "mysql",
@@ -43,20 +68,16 @@ const dataSource = new DataSource({
43
68
  entities: [],
44
69
  });
45
70
 
46
- registerTransactionalTestHooks({
47
- dataSource,
48
- hooks: {
49
- beforeEach,
50
- afterEach,
51
- },
71
+ const lifecycle = TypeormTestDB(dataSource, {
72
+ isolationLevel: "REPEATABLE READ",
52
73
  });
53
74
 
54
- beforeAll(async () => {
55
- await dataSource.initialize();
75
+ beforeEach(async () => {
76
+ await lifecycle.init();
56
77
  });
57
78
 
58
- afterAll(async () => {
59
- await dataSource.destroy();
79
+ afterEach(async () => {
80
+ await lifecycle.finish();
60
81
  });
61
82
  ```
62
83
 
@@ -64,7 +85,7 @@ Import your repositories or managers inside the specs. Every mutation executed b
64
85
 
65
86
  ## Test Execution
66
87
 
67
- The suite seeds reproducible fixtures per spec and exposes the `TEST_SEED` environment variable to control execution order. `pnpm test` runs Jest in parallel workers, enforces coverage collection, and builds the package beforehand so the compiled output is exercised.
88
+ The suite seeds reproducible fixtures per spec and exposes the `TEST_SEED` environment variable to control execution order. `pnpm test` runs Jest in parallel workers and enforces coverage collection.
68
89
 
69
90
  ## Continuous Integration
70
91
 
package/README.es.md CHANGED
@@ -6,31 +6,56 @@ TypeORM Test DB envuelve cada spec de Jest en una transacción de base de datos
6
6
 
7
7
  ## Características
8
8
 
9
- - Helper de ciclo de vida transaccional con hooks explícitos `init` y `finish`.
10
- - Registro de hooks de Jest que abre y revierte transacciones automáticamente.
9
+ - Helper del ciclo de vida de la base de datos de pruebas para TypeORM con hooks explícitos `init` y `finish`.
10
+ - Integración agnóstica del framework invocando el ciclo de vida dentro de los hooks del runner de pruebas.
11
11
  - Compatibilidad con MySQL, MariaDB, PostgreSQL, SQLite y Better SQLite 3.
12
- - Fabricas de datos deterministas impulsadas por una semilla de ejecución reproducible.
12
+ - Fábricas de datos deterministas impulsadas por una semilla de ejecución reproducible.
13
13
  - Configuración de pruebas compartida que inicializa una única conexión por worker y ejecuta las specs en paralelo.
14
14
  - Informes de cobertura generados por defecto mediante `pnpm test`.
15
15
  - Artefactos de build generados por `pnpm build` y consumidos por Jest para simular una instalación del paquete.
16
16
 
17
17
  ## Instalación
18
18
 
19
+ <details>
20
+ <summary>pnpm</summary>
21
+
22
+ ```bash
23
+ pnpm add -D typeorm-test-db
24
+ pnpm add typeorm
25
+ ```
26
+
27
+ </details>
28
+
29
+ <details>
30
+ <summary>npm</summary>
31
+
19
32
  ```bash
20
- pnpm add typeorm-test-db
21
- pnpm add typeorm # dependencia peer obligatoria
33
+ npm install -D typeorm-test-db
34
+ npm install typeorm
22
35
  ```
23
36
 
37
+ </details>
38
+
39
+ <details>
40
+ <summary>Yarn</summary>
41
+
42
+ ```bash
43
+ yarn add -D typeorm-test-db
44
+ yarn add typeorm
45
+ ```
46
+
47
+ </details>
48
+
24
49
  Instala TypeORM en el proyecto anfitrión si aún no está disponible.
25
50
 
26
51
  ## Uso
27
52
 
28
- Crea un archivo de configuración de Jest que inicialice la conexión y registre el ciclo de vida transaccional.
53
+ Crea un archivo de configuración de Jest que inicialice la conexión y registre el ciclo de vida de la base de datos de pruebas para TypeORM.
29
54
 
30
55
  ```typescript
31
56
  import { afterAll, afterEach, beforeAll, beforeEach } from "@jest/globals";
32
57
  import { DataSource } from "typeorm";
33
- import { registerTransactionalTestHooks } from "typeorm-test-db";
58
+ import { TypeormTestDB } from "typeorm-test-db";
34
59
 
35
60
  const dataSource = new DataSource({
36
61
  type: "mysql",
@@ -43,20 +68,16 @@ const dataSource = new DataSource({
43
68
  entities: [],
44
69
  });
45
70
 
46
- registerTransactionalTestHooks({
47
- dataSource,
48
- hooks: {
49
- beforeEach,
50
- afterEach,
51
- },
71
+ const lifecycle = TypeormTestDB(dataSource, {
72
+ isolationLevel: "REPEATABLE READ",
52
73
  });
53
74
 
54
- beforeAll(async () => {
55
- await dataSource.initialize();
75
+ beforeEach(async () => {
76
+ await lifecycle.init();
56
77
  });
57
78
 
58
- afterAll(async () => {
59
- await dataSource.destroy();
79
+ afterEach(async () => {
80
+ await lifecycle.finish();
60
81
  });
61
82
  ```
62
83
 
@@ -74,7 +95,7 @@ El workflow de GitHub Actions ejecuta el linting y la suite de Jest contra una m
74
95
 
75
96
  - `pnpm lint` verifica la calidad del código.
76
97
  - `pnpm build` genera el bundle de producción en `dist`.
77
- - `pnpm test` recompila el paquete, ejecuta las pruebas con datos semilla y comprueba que el tarball se pueda instalar en un proyecto limpio.
98
+ - `pnpm test` recompila el paquete y ejecuta las pruebas con datos semilla.
78
99
 
79
100
  ## Licencia
80
101
 
package/README.pt.md CHANGED
@@ -6,8 +6,8 @@ TypeORM Test DB envolve cada spec do Jest em uma transação de banco de dados i
6
6
 
7
7
  ## Recursos
8
8
 
9
- - Helper de ciclo de vida transacional com hooks explícitos `init` e `finish`.
10
- - Registro de hooks do Jest que abre e reverte transações automaticamente.
9
+ - Helper do ciclo de vida do banco de dados de testes para TypeORM com hooks explícitos `init` e `finish`.
10
+ - Integração agnóstica de framework ao invocar o ciclo de vida dentro dos hooks do runner de testes.
11
11
  - Compatibilidade com MySQL, MariaDB, PostgreSQL, SQLite e Better SQLite 3.
12
12
  - Fábricas de dados determinísticas impulsionadas por uma semente de execução reproduzível.
13
13
  - Configuração de testes compartilhada que inicializa uma única conexão por worker e executa as specs em paralelo.
@@ -16,21 +16,46 @@ TypeORM Test DB envolve cada spec do Jest em uma transação de banco de dados i
16
16
 
17
17
  ## Instalação
18
18
 
19
+ <details>
20
+ <summary>pnpm</summary>
21
+
22
+ ```bash
23
+ pnpm add -D typeorm-test-db
24
+ pnpm add typeorm
25
+ ```
26
+
27
+ </details>
28
+
29
+ <details>
30
+ <summary>npm</summary>
31
+
19
32
  ```bash
20
- pnpm add typeorm-test-db
21
- pnpm add typeorm # dependência peer obrigatória
33
+ npm install -D typeorm-test-db
34
+ npm install typeorm
22
35
  ```
23
36
 
37
+ </details>
38
+
39
+ <details>
40
+ <summary>Yarn</summary>
41
+
42
+ ```bash
43
+ yarn add -D typeorm-test-db
44
+ yarn add typeorm
45
+ ```
46
+
47
+ </details>
48
+
24
49
  Instale o TypeORM no projeto hospedeiro caso ainda não esteja disponível.
25
50
 
26
51
  ## Uso
27
52
 
28
- Crie um arquivo de configuração do Jest que inicialize a conexão e registre o ciclo de vida transacional.
53
+ Crie um arquivo de configuração do Jest que inicialize a conexão e registre o ciclo de vida do banco de dados de testes para TypeORM.
29
54
 
30
55
  ```typescript
31
56
  import { afterAll, afterEach, beforeAll, beforeEach } from "@jest/globals";
32
57
  import { DataSource } from "typeorm";
33
- import { registerTransactionalTestHooks } from "typeorm-test-db";
58
+ import { TypeormTestDB } from "typeorm-test-db";
34
59
 
35
60
  const dataSource = new DataSource({
36
61
  type: "mysql",
@@ -43,20 +68,16 @@ const dataSource = new DataSource({
43
68
  entities: [],
44
69
  });
45
70
 
46
- registerTransactionalTestHooks({
47
- dataSource,
48
- hooks: {
49
- beforeEach,
50
- afterEach,
51
- },
71
+ const lifecycle = TypeormTestDB(dataSource, {
72
+ isolationLevel: "REPEATABLE READ",
52
73
  });
53
74
 
54
- beforeAll(async () => {
55
- await dataSource.initialize();
75
+ beforeEach(async () => {
76
+ await lifecycle.init();
56
77
  });
57
78
 
58
- afterAll(async () => {
59
- await dataSource.destroy();
79
+ afterEach(async () => {
80
+ await lifecycle.finish();
60
81
  });
61
82
  ```
62
83
 
@@ -64,7 +85,7 @@ Importe seus repositórios ou managers dentro das specs. Todas as mutações exe
64
85
 
65
86
  ## Execução dos testes
66
87
 
67
- A suíte gera dados reproduzíveis por spec e expõe a variável de ambiente `TEST_SEED` para controlar a ordem de execução. `pnpm test` executa o Jest em workers paralelos, força a coleta de cobertura e compila o pacote antes das provas para exercitar a saída empacotada.
88
+ A suíte gera dados reproduzíveis por spec e expõe a variável de ambiente `TEST_SEED` para controlar a ordem de execução. `pnpm test` executa o Jest em workers paralelos e força a coleta de cobertura.
68
89
 
69
90
  ## Integração contínua
70
91
 
@@ -1,6 +1,6 @@
1
1
  export declare const errorMessages: {
2
- readonly dataSourceNotInitialized: "Transactional tests require an initialized data source.";
3
- readonly transactionAlreadyStarted: "A transactional test context is already active for the provided data source.";
4
- readonly transactionCallbackMissing: "Transactional execution requires a callback to operate on the shared entity manager.";
2
+ readonly dataSourceNotInitialized: "TypeORM test database context requires an initialized data source.";
3
+ readonly transactionAlreadyStarted: "A TypeORM test database context is already active for the provided data source.";
4
+ readonly transactionCallbackMissing: "TypeORM test database execution requires a callback to operate on the shared entity manager.";
5
5
  };
6
6
  //# sourceMappingURL=messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/constants/messages.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa;;;;CAIhB,CAAC"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/constants/messages.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa;;;;CAKhB,CAAC"}
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.errorMessages = void 0;
4
4
  exports.errorMessages = {
5
- dataSourceNotInitialized: 'Transactional tests require an initialized data source.',
6
- transactionAlreadyStarted: 'A transactional test context is already active for the provided data source.',
7
- transactionCallbackMissing: 'Transactional execution requires a callback to operate on the shared entity manager.'
5
+ dataSourceNotInitialized: 'TypeORM test database context requires an initialized data source.',
6
+ transactionAlreadyStarted: 'A TypeORM test database context is already active for the provided data source.',
7
+ transactionCallbackMissing: 'TypeORM test database execution requires a callback to operate on the shared entity manager.'
8
8
  };
9
9
  //# sourceMappingURL=messages.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/constants/messages.ts"],"names":[],"mappings":";;;AAAa,QAAA,aAAa,GAAG;IAC3B,wBAAwB,EAAE,yDAAyD;IACnF,yBAAyB,EAAE,8EAA8E;IACzG,0BAA0B,EAAE,sFAAsF;CAC1G,CAAC"}
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/constants/messages.ts"],"names":[],"mappings":";;;AAAa,QAAA,aAAa,GAAG;IAC3B,wBAAwB,EAAE,oEAAoE;IAC9F,yBAAyB,EAAE,iFAAiF;IAC5G,0BAA0B,EACxB,8FAA8F;CACxF,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,6 @@
1
- import type { DataSource } from 'typeorm';
2
- import { type TransactionalTestLifecycle } from './lifecycle/TransactionalTestContext';
3
- import { registerTransactionalTestHooks } from './lifecycle/registerTransactionalHooks';
4
- export declare const createTransactionalTestContext: (dataSource: DataSource) => TransactionalTestLifecycle;
5
- export { registerTransactionalTestHooks };
6
- export type { TransactionalTestLifecycle } from './lifecycle/TransactionalTestContext';
7
- export type { RegisterTransactionalTestHooksOptions, RegisteredTransactionalTestHooks, TransactionalTestHooks } from './lifecycle/registerTransactionalHooks';
1
+ import type { DataSource } from "typeorm";
2
+ import { TypeormTestDb, type TypeormTestDbOptions } from "./lifecycle/TypeormTestDb";
3
+ export declare const TypeormTestDB: (dataSource: DataSource, options?: TypeormTestDbOptions) => TypeormTestDb;
4
+ export { TypeormTestDb };
5
+ export type { TypeormTestDbOptions };
8
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAA4B,KAAK,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AACjH,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AAExF,eAAO,MAAM,8BAA8B,eAAgB,UAAU,KAAG,0BAEvE,CAAC;AAEF,OAAO,EAAE,8BAA8B,EAAE,CAAC;AAE1C,YAAY,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AACvF,YAAY,EACV,qCAAqC,EACrC,gCAAgC,EAChC,sBAAsB,EACvB,MAAM,wCAAwC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAErF,eAAO,MAAM,aAAa,GACxB,YAAY,UAAU,EACtB,UAAU,oBAAoB,KAC7B,aAEF,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC;AACzB,YAAY,EAAE,oBAAoB,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerTransactionalTestHooks = exports.createTransactionalTestContext = void 0;
4
- const TransactionalTestContext_1 = require("./lifecycle/TransactionalTestContext");
5
- const registerTransactionalHooks_1 = require("./lifecycle/registerTransactionalHooks");
6
- Object.defineProperty(exports, "registerTransactionalTestHooks", { enumerable: true, get: function () { return registerTransactionalHooks_1.registerTransactionalTestHooks; } });
7
- const createTransactionalTestContext = (dataSource) => {
8
- return new TransactionalTestContext_1.TransactionalTestContext(dataSource);
3
+ exports.TypeormTestDb = exports.TypeormTestDB = void 0;
4
+ const TypeormTestDb_1 = require("./lifecycle/TypeormTestDb");
5
+ Object.defineProperty(exports, "TypeormTestDb", { enumerable: true, get: function () { return TypeormTestDb_1.TypeormTestDb; } });
6
+ const TypeormTestDB = (dataSource, options) => {
7
+ return new TypeormTestDb_1.TypeormTestDb(dataSource, options);
9
8
  };
10
- exports.createTransactionalTestContext = createTransactionalTestContext;
9
+ exports.TypeormTestDB = TypeormTestDB;
11
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,mFAAiH;AACjH,uFAAwF;AAM/E,+GANA,2DAA8B,OAMA;AAJhC,MAAM,8BAA8B,GAAG,CAAC,UAAsB,EAA8B,EAAE;IACnG,OAAO,IAAI,mDAAwB,CAAC,UAAU,CAAC,CAAC;AAClD,CAAC,CAAC;AAFW,QAAA,8BAA8B,kCAEzC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,6DAAqF;AAS5E,8FATA,6BAAa,OASA;AAPf,MAAM,aAAa,GAAG,CAC3B,UAAsB,EACtB,OAA8B,EACf,EAAE;IACjB,OAAO,IAAI,6BAAa,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC,CAAC;AALW,QAAA,aAAa,iBAKxB"}
@@ -0,0 +1,14 @@
1
+ import type { DataSource } from "typeorm";
2
+ import type { IsolationLevel } from "typeorm/driver/types/IsolationLevel";
3
+ export interface TypeormTestDbOptions {
4
+ readonly isolationLevel?: IsolationLevel;
5
+ }
6
+ export declare class TypeormTestDb {
7
+ private readonly dataSource;
8
+ private readonly isolationLevel;
9
+ private readonly isolationContext;
10
+ constructor(dataSource: DataSource, options?: TypeormTestDbOptions);
11
+ readonly init: () => Promise<void>;
12
+ readonly finish: () => Promise<void>;
13
+ }
14
+ //# sourceMappingURL=TypeormTestDb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypeormTestDb.d.ts","sourceRoot":"","sources":["../../src/lifecycle/TypeormTestDb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAO1E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;CAC1C;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA6C;gBAElE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,oBAAoB;IAMlE,SAAgB,IAAI,QAAa,OAAO,CAAC,IAAI,CAAC,CAyB5C;IAEF,SAAgB,MAAM,QAAa,OAAO,CAAC,IAAI,CAAC,CAiB9C;CACH"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeormTestDb = void 0;
4
+ const messages_1 = require("../constants/messages");
5
+ const isolation_context_1 = require("./isolation-context");
6
+ class TypeormTestDb {
7
+ constructor(dataSource, options) {
8
+ this.init = async () => {
9
+ if (!this.dataSource.isInitialized) {
10
+ throw new Error(messages_1.errorMessages.dataSourceNotInitialized);
11
+ }
12
+ const activeStore = this.isolationContext.getStore();
13
+ if (activeStore?.active === true) {
14
+ throw new Error(messages_1.errorMessages.transactionAlreadyStarted);
15
+ }
16
+ const queryRunner = this.dataSource.createQueryRunner();
17
+ await queryRunner.connect();
18
+ await queryRunner.startTransaction(this.isolationLevel);
19
+ const store = {
20
+ queryRunner,
21
+ manager: this.isolationContext.createTransactionalManager(queryRunner.manager, queryRunner),
22
+ active: false,
23
+ savepointCounter: 0,
24
+ };
25
+ this.isolationContext.useStore(store);
26
+ };
27
+ this.finish = async () => {
28
+ const store = this.isolationContext.getStore();
29
+ if (store === undefined) {
30
+ return;
31
+ }
32
+ const { queryRunner } = store;
33
+ try {
34
+ if (queryRunner.isTransactionActive) {
35
+ await queryRunner.rollbackTransaction();
36
+ }
37
+ }
38
+ finally {
39
+ this.isolationContext.clearStore(store);
40
+ await queryRunner.release();
41
+ }
42
+ };
43
+ this.dataSource = dataSource;
44
+ this.isolationLevel = options?.isolationLevel;
45
+ this.isolationContext = (0, isolation_context_1.resolveIsolationContext)(dataSource);
46
+ }
47
+ }
48
+ exports.TypeormTestDb = TypeormTestDb;
49
+ //# sourceMappingURL=TypeormTestDb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypeormTestDb.js","sourceRoot":"","sources":["../../src/lifecycle/TypeormTestDb.ts"],"names":[],"mappings":";;;AAEA,oDAAsD;AACtD,2DAG6B;AAM7B,MAAa,aAAa;IAKxB,YAAY,UAAsB,EAAE,OAA8B;QAMlD,SAAI,GAAG,KAAK,IAAmB,EAAE;YAC/C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,wBAAa,CAAC,wBAAwB,CAAC,CAAC;YAC1D,CAAC;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;YACrD,IAAI,WAAW,EAAE,MAAM,KAAK,IAAI,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CAAC,wBAAa,CAAC,yBAAyB,CAAC,CAAC;YAC3D,CAAC;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC;YACxD,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;YAC5B,MAAM,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAExD,MAAM,KAAK,GAAqB;gBAC9B,WAAW;gBACX,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAAC,0BAA0B,CACvD,WAAW,CAAC,OAAO,EACnB,WAAW,CACZ;gBACD,MAAM,EAAE,KAAK;gBACb,gBAAgB,EAAE,CAAC;aACpB,CAAC;YAEF,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC,CAAC;QAEc,WAAM,GAAG,KAAK,IAAmB,EAAE;YACjD,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;YAE/C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO;YACT,CAAC;YAED,MAAM,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;YAE9B,IAAI,CAAC;gBACH,IAAI,WAAW,CAAC,mBAAmB,EAAE,CAAC;oBACpC,MAAM,WAAW,CAAC,mBAAmB,EAAE,CAAC;gBAC1C,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;gBACxC,MAAM,WAAW,CAAC,OAAO,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC;QAjDA,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,OAAO,EAAE,cAAc,CAAC;QAC9C,IAAI,CAAC,gBAAgB,GAAG,IAAA,2CAAuB,EAAC,UAAU,CAAC,CAAC;IAC9D,CAAC;CA+CF;AAxDD,sCAwDC"}
@@ -0,0 +1,39 @@
1
+ import type { DataSource, EntityManager, QueryRunner } from "typeorm";
2
+ export type TransactionStore = {
3
+ readonly queryRunner: QueryRunner;
4
+ readonly manager: EntityManager;
5
+ active: boolean;
6
+ savepointCounter: number;
7
+ };
8
+ declare class DataSourceIsolationContext {
9
+ private readonly dataSource;
10
+ private readonly lockingDrivers;
11
+ private readonly storage;
12
+ private readonly namedStores;
13
+ private readonly pendingStores;
14
+ private readonly managerDescriptor;
15
+ private fallbackManager;
16
+ private readonly originalDataSourceTransaction;
17
+ constructor(dataSource: DataSource);
18
+ useStore(store: TransactionStore): void;
19
+ clearStore(store: TransactionStore): void;
20
+ getStore(): TransactionStore | undefined;
21
+ private resolveInitialManager;
22
+ private patchManagerProperty;
23
+ private patchDataSourceTransaction;
24
+ createTransactionalManager(originalManager: EntityManager, queryRunner: QueryRunner): EntityManager;
25
+ runWithStoreTransaction<TResult>(store: TransactionStore, operation: () => Promise<TResult>): Promise<TResult>;
26
+ private generateSavepointName;
27
+ private createSavepoint;
28
+ private rollbackToSavepoint;
29
+ private releaseSavepoint;
30
+ private withPessimisticLock;
31
+ private extractLockCriteria;
32
+ private normalizeWhere;
33
+ private acquirePessimisticLock;
34
+ private shouldRetry;
35
+ private delayForRetry;
36
+ }
37
+ export declare const resolveIsolationContext: (dataSource: DataSource) => DataSourceIsolationContext;
38
+ export {};
39
+ //# sourceMappingURL=isolation-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isolation-context.d.ts","sourceRoot":"","sources":["../../src/lifecycle/isolation-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAA+B,WAAW,EAAc,MAAM,SAAS,CAAC;AAU/G,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAaF,cAAM,0BAA0B;IAalB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAZrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6C;IAC9E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyD;IACjF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;IACnE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA0B;IACxD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAE6C;IAC/E,OAAO,CAAC,eAAe,CAA+C;IACtE,OAAO,CAAC,QAAQ,CAAC,6BAA6B,CAExB;gBAEO,UAAU,EAAE,UAAU;IAQ5C,QAAQ,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAWvC,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAoBzC,QAAQ,IAAI,gBAAgB,GAAG,SAAS;IAyB/C,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,oBAAoB;IAkC5B,OAAO,CAAC,0BAA0B;IAsB7B,0BAA0B,CAC/B,eAAe,EAAE,aAAa,EAC9B,WAAW,EAAE,WAAW,GACvB,aAAa;IA8FD,uBAAuB,CAAC,OAAO,EAC1C,KAAK,EAAE,gBAAgB,EACvB,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAChC,OAAO,CAAC,OAAO,CAAC;IA4BnB,OAAO,CAAC,qBAAqB;YAKf,eAAe;YAOf,mBAAmB;YAWnB,gBAAgB;YAWhB,mBAAmB;IA2BjC,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,cAAc;YAuBR,sBAAsB;IA2CpC,OAAO,CAAC,WAAW;YAkBL,aAAa;CAI5B;AAgFD,eAAO,MAAM,uBAAuB,GAClC,YAAY,UAAU,KACrB,0BAQF,CAAC"}
@@ -0,0 +1,428 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveIsolationContext = void 0;
4
+ const node_async_hooks_1 = require("node:async_hooks");
5
+ const typeorm_1 = require("typeorm");
6
+ const messages_1 = require("../constants/messages");
7
+ const savepointPrefix = "ttdb_savepoint_";
8
+ const maxTransactionAttempts = 5;
9
+ const retryDelayBaseMs = 5;
10
+ const retryableMessageFragments = [
11
+ "deadlock found when trying to get lock",
12
+ "lock wait timeout exceeded",
13
+ "record has changed since last read",
14
+ "database is locked",
15
+ "busy",
16
+ ];
17
+ class DataSourceIsolationContext {
18
+ constructor(dataSource) {
19
+ this.dataSource = dataSource;
20
+ this.lockingDrivers = new Set(["mysql", "mariadb", "postgres"]);
21
+ this.storage = new node_async_hooks_1.AsyncLocalStorage();
22
+ this.namedStores = new Map();
23
+ this.pendingStores = [];
24
+ this.managerDescriptor = Object.getOwnPropertyDescriptor(this.dataSource, "manager") ?? null;
25
+ this.fallbackManager = this.resolveInitialManager();
26
+ this.originalDataSourceTransaction = this.dataSource.transaction.bind(this.dataSource);
27
+ this.patchManagerProperty();
28
+ this.patchDataSourceTransaction();
29
+ }
30
+ useStore(store) {
31
+ store.active = true;
32
+ this.storage.enterWith(store);
33
+ const testKey = resolveCurrentTestKey();
34
+ if (testKey !== null) {
35
+ this.namedStores.set(testKey, store);
36
+ return;
37
+ }
38
+ this.pendingStores.push(store);
39
+ }
40
+ clearStore(store) {
41
+ store.active = false;
42
+ const current = this.storage.getStore();
43
+ if (current === store) {
44
+ this.storage.enterWith(undefined);
45
+ }
46
+ const testKey = resolveCurrentTestKey();
47
+ if (testKey !== null) {
48
+ const mappedStore = this.namedStores.get(testKey);
49
+ if (mappedStore === store) {
50
+ this.namedStores.delete(testKey);
51
+ }
52
+ }
53
+ else {
54
+ const index = this.pendingStores.indexOf(store);
55
+ if (index !== -1) {
56
+ this.pendingStores.splice(index, 1);
57
+ }
58
+ }
59
+ }
60
+ getStore() {
61
+ const activeStore = this.storage.getStore();
62
+ if (activeStore?.active === true) {
63
+ return activeStore;
64
+ }
65
+ const testKey = resolveCurrentTestKey();
66
+ if (testKey !== null) {
67
+ let namedStore = this.namedStores.get(testKey);
68
+ if (namedStore === undefined && this.pendingStores.length > 0) {
69
+ const pending = this.pendingStores.shift();
70
+ if (pending !== undefined) {
71
+ this.namedStores.set(testKey, pending);
72
+ namedStore = pending;
73
+ }
74
+ }
75
+ if (namedStore?.active === true) {
76
+ this.storage.enterWith(namedStore);
77
+ return namedStore;
78
+ }
79
+ }
80
+ return activeStore;
81
+ }
82
+ resolveInitialManager() {
83
+ if (this.managerDescriptor?.get !== undefined) {
84
+ const resolved = this.managerDescriptor.get.call(this.dataSource);
85
+ if (resolved !== undefined) {
86
+ return resolved;
87
+ }
88
+ }
89
+ return this.dataSource.manager;
90
+ }
91
+ patchManagerProperty() {
92
+ const context = this;
93
+ const descriptor = this.managerDescriptor;
94
+ Object.defineProperty(this.dataSource, "manager", {
95
+ configurable: true,
96
+ enumerable: true,
97
+ get() {
98
+ const store = context.storage.getStore();
99
+ if (store?.active === true) {
100
+ return store.manager;
101
+ }
102
+ const testKey = resolveCurrentTestKey();
103
+ if (testKey !== null) {
104
+ const namedStore = context.namedStores.get(testKey);
105
+ if (namedStore?.active === true) {
106
+ context.storage.enterWith(namedStore);
107
+ return namedStore.manager;
108
+ }
109
+ }
110
+ if (descriptor?.get !== undefined) {
111
+ return descriptor.get.call(this);
112
+ }
113
+ return context.fallbackManager;
114
+ },
115
+ set(manager) {
116
+ if (descriptor?.set !== undefined) {
117
+ descriptor.set.call(this, manager);
118
+ }
119
+ context.fallbackManager = manager;
120
+ },
121
+ });
122
+ }
123
+ patchDataSourceTransaction() {
124
+ const context = this;
125
+ this.dataSource.transaction = (async function patchedTransaction(...args) {
126
+ const store = context.getStore();
127
+ if (store?.active === true) {
128
+ const callback = findTransactionCallback(args);
129
+ if (callback === null) {
130
+ throw new Error(messages_1.errorMessages.transactionCallbackMissing);
131
+ }
132
+ return await context.runWithStoreTransaction(store, async () => {
133
+ return await callback(store.manager);
134
+ });
135
+ }
136
+ return context.originalDataSourceTransaction(...args);
137
+ });
138
+ }
139
+ createTransactionalManager(originalManager, queryRunner) {
140
+ const driver = (queryRunner.connection.options.type ?? "").toLowerCase();
141
+ if (!this.lockingDrivers.has(driver)) {
142
+ return originalManager;
143
+ }
144
+ const repositoryCache = new WeakMap();
145
+ const wrapRepository = (repository) => {
146
+ if (repository === null || typeof repository !== "object") {
147
+ return repository;
148
+ }
149
+ const cached = repositoryCache.get(repository);
150
+ if (cached !== undefined) {
151
+ return cached;
152
+ }
153
+ const proxy = new Proxy(repository, {
154
+ get: (target, property, receiver) => {
155
+ if (property === "findOne" ||
156
+ property === "findOneOrFail" ||
157
+ property === "findOneBy" ||
158
+ property === "findOneByOrFail") {
159
+ const original = Reflect.get(target, property, receiver);
160
+ if (typeof original !== "function") {
161
+ return original;
162
+ }
163
+ return (...fnArgs) => {
164
+ return this.withPessimisticLock(queryRunner, target, property.toString(), fnArgs, () => original.apply(target, fnArgs));
165
+ };
166
+ }
167
+ return Reflect.get(target, property, receiver);
168
+ },
169
+ });
170
+ repositoryCache.set(repository, proxy);
171
+ return proxy;
172
+ };
173
+ return new Proxy(originalManager, {
174
+ get: (target, property, receiver) => {
175
+ if (property === "findOne" ||
176
+ property === "findOneOrFail" ||
177
+ property === "findOneBy" ||
178
+ property === "findOneByOrFail") {
179
+ const original = Reflect.get(target, property, receiver);
180
+ if (typeof original !== "function") {
181
+ return original;
182
+ }
183
+ return (...fnArgs) => {
184
+ if (fnArgs.length === 0) {
185
+ return original.apply(target, fnArgs);
186
+ }
187
+ const [entity, ...rest] = fnArgs;
188
+ const repository = target.getRepository(entity);
189
+ return this.withPessimisticLock(queryRunner, repository, property.toString(), rest, () => original.apply(target, fnArgs));
190
+ };
191
+ }
192
+ if (property === "getRepository") {
193
+ const original = Reflect.get(target, property, receiver);
194
+ if (typeof original !== "function") {
195
+ return original;
196
+ }
197
+ return (...repoArgs) => {
198
+ const repository = original.apply(target, repoArgs);
199
+ return wrapRepository(repository);
200
+ };
201
+ }
202
+ return Reflect.get(target, property, receiver);
203
+ },
204
+ });
205
+ }
206
+ async runWithStoreTransaction(store, operation) {
207
+ const runner = store.queryRunner;
208
+ if (!runner.isTransactionActive || runner.isReleased) {
209
+ return await operation();
210
+ }
211
+ let attempt = 0;
212
+ while (attempt < maxTransactionAttempts) {
213
+ const savepoint = this.generateSavepointName(store);
214
+ await this.createSavepoint(runner, savepoint);
215
+ try {
216
+ const result = await operation();
217
+ await this.releaseSavepoint(runner, savepoint);
218
+ return result;
219
+ }
220
+ catch (error) {
221
+ await this.rollbackToSavepoint(runner, savepoint);
222
+ await this.releaseSavepoint(runner, savepoint);
223
+ attempt += 1;
224
+ if (!this.shouldRetry(error) || attempt >= maxTransactionAttempts) {
225
+ throw error;
226
+ }
227
+ await this.delayForRetry(attempt);
228
+ }
229
+ }
230
+ throw new Error("Exceeded maximum transaction retry attempts.");
231
+ }
232
+ generateSavepointName(store) {
233
+ store.savepointCounter += 1;
234
+ return `${savepointPrefix}${store.savepointCounter}`;
235
+ }
236
+ async createSavepoint(queryRunner, name) {
237
+ await queryRunner.query(`SAVEPOINT ${name}`);
238
+ }
239
+ async rollbackToSavepoint(queryRunner, name) {
240
+ try {
241
+ await queryRunner.query(`ROLLBACK TO SAVEPOINT ${name}`);
242
+ }
243
+ catch {
244
+ // ignore failures so that retries can continue
245
+ }
246
+ }
247
+ async releaseSavepoint(queryRunner, name) {
248
+ try {
249
+ await queryRunner.query(`RELEASE SAVEPOINT ${name}`);
250
+ }
251
+ catch {
252
+ // ignore
253
+ }
254
+ }
255
+ async withPessimisticLock(queryRunner, repositoryTarget, method, args, invocation) {
256
+ const driver = (queryRunner.connection.options.type ?? "").toLowerCase();
257
+ if (!this.lockingDrivers.has(driver)) {
258
+ return await Promise.resolve(invocation());
259
+ }
260
+ const repository = repositoryTarget;
261
+ const criteria = this.extractLockCriteria(method, args);
262
+ if (criteria === null) {
263
+ return await Promise.resolve(invocation());
264
+ }
265
+ try {
266
+ await this.acquirePessimisticLock(queryRunner, repository, criteria);
267
+ }
268
+ catch {
269
+ // Best-effort locking; continue even if lock acquisition fails.
270
+ }
271
+ return await Promise.resolve(invocation());
272
+ }
273
+ extractLockCriteria(method, args) {
274
+ if (method === "findOne" || method === "findOneOrFail") {
275
+ const [options] = args;
276
+ if (options !== null &&
277
+ typeof options === "object" &&
278
+ !Array.isArray(options) &&
279
+ "where" in options) {
280
+ return this.normalizeWhere(options.where);
281
+ }
282
+ return null;
283
+ }
284
+ if (method === "findOneBy" || method === "findOneByOrFail") {
285
+ const [where] = args;
286
+ return this.normalizeWhere(where);
287
+ }
288
+ return null;
289
+ }
290
+ normalizeWhere(value) {
291
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
292
+ return null;
293
+ }
294
+ const entries = Object.entries(value);
295
+ const normalized = {};
296
+ for (const [key, candidate] of entries) {
297
+ if (typeof candidate === "string" ||
298
+ typeof candidate === "number" ||
299
+ typeof candidate === "boolean" ||
300
+ candidate === null) {
301
+ normalized[key] = candidate;
302
+ }
303
+ else {
304
+ return null;
305
+ }
306
+ }
307
+ return Object.keys(normalized).length > 0 ? normalized : null;
308
+ }
309
+ async acquirePessimisticLock(queryRunner, repository, criteria) {
310
+ const alias = "lock_target";
311
+ const qb = queryRunner.manager
312
+ .createQueryBuilder(repository.metadata.target, alias)
313
+ .select("1")
314
+ .setLock("pessimistic_write")
315
+ .limit(1);
316
+ const parameters = {};
317
+ let index = 0;
318
+ for (const [property, value] of Object.entries(criteria)) {
319
+ const column = repository.metadata.findColumnWithPropertyPath(property);
320
+ if (column === undefined) {
321
+ return;
322
+ }
323
+ index += 1;
324
+ const paramName = `lock_param_${index}`;
325
+ const escapedColumn = `${alias}.${queryRunner.connection.driver.escape(column.databaseName)}`;
326
+ if (index === 1) {
327
+ qb.where(`${escapedColumn} = :${paramName}`);
328
+ }
329
+ else {
330
+ qb.andWhere(`${escapedColumn} = :${paramName}`);
331
+ }
332
+ parameters[paramName] = value;
333
+ }
334
+ if (index === 0) {
335
+ return;
336
+ }
337
+ qb.setParameters(parameters);
338
+ await qb.getRawOne();
339
+ }
340
+ shouldRetry(error) {
341
+ if (!(error instanceof Error)) {
342
+ return false;
343
+ }
344
+ const message = error.message.toLowerCase();
345
+ if (retryableMessageFragments.some((fragment) => message.includes(fragment))) {
346
+ return true;
347
+ }
348
+ const anyError = error;
349
+ if (typeof anyError.code === "string") {
350
+ const code = anyError.code.toUpperCase();
351
+ if (code === "ER_LOCK_DEADLOCK" || code === "ER_LOCK_WAIT_TIMEOUT") {
352
+ return true;
353
+ }
354
+ }
355
+ return false;
356
+ }
357
+ async delayForRetry(attempt) {
358
+ const delay = retryDelayBaseMs * attempt * attempt;
359
+ await new Promise((resolve) => setTimeout(resolve, delay));
360
+ }
361
+ }
362
+ const resolveCurrentTestKey = () => {
363
+ const maybeExpect = globalThis.expect;
364
+ if (maybeExpect !== undefined && maybeExpect !== null) {
365
+ const getState = maybeExpect.getState;
366
+ if (typeof getState === "function") {
367
+ const state = getState();
368
+ if (state !== undefined && state !== null) {
369
+ const { currentTestName, testPath } = state;
370
+ const keyParts = [];
371
+ if (typeof testPath === "string" && testPath.length > 0) {
372
+ keyParts.push(testPath);
373
+ }
374
+ if (typeof currentTestName === "string" && currentTestName.length > 0) {
375
+ keyParts.push(currentTestName);
376
+ }
377
+ if (keyParts.length > 0) {
378
+ return keyParts.join("::");
379
+ }
380
+ }
381
+ }
382
+ }
383
+ return null;
384
+ };
385
+ const dataSourceContexts = new WeakMap();
386
+ const originalEntityManagerTransaction = typeorm_1.EntityManager.prototype.transaction;
387
+ let entityManagerTransactionPatched = false;
388
+ const findTransactionCallback = (args) => {
389
+ const [first, second] = args;
390
+ if (typeof first === "function") {
391
+ return first;
392
+ }
393
+ if (typeof second === "function") {
394
+ return second;
395
+ }
396
+ return null;
397
+ };
398
+ const ensureEntityManagerTransactionPatched = () => {
399
+ if (entityManagerTransactionPatched) {
400
+ return;
401
+ }
402
+ typeorm_1.EntityManager.prototype.transaction = async function patchedManagerTransaction(...args) {
403
+ const context = dataSourceContexts.get(this.connection);
404
+ const store = context?.getStore();
405
+ if (context !== undefined && store?.active === true) {
406
+ const callback = findTransactionCallback(args);
407
+ if (callback === null) {
408
+ throw new Error(messages_1.errorMessages.transactionCallbackMissing);
409
+ }
410
+ return await context.runWithStoreTransaction(store, async () => {
411
+ return await callback(store.manager);
412
+ });
413
+ }
414
+ return originalEntityManagerTransaction.apply(this, args);
415
+ };
416
+ entityManagerTransactionPatched = true;
417
+ };
418
+ const resolveIsolationContext = (dataSource) => {
419
+ let context = dataSourceContexts.get(dataSource);
420
+ if (context === undefined) {
421
+ ensureEntityManagerTransactionPatched();
422
+ context = new DataSourceIsolationContext(dataSource);
423
+ dataSourceContexts.set(dataSource, context);
424
+ }
425
+ return context;
426
+ };
427
+ exports.resolveIsolationContext = resolveIsolationContext;
428
+ //# sourceMappingURL=isolation-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isolation-context.js","sourceRoot":"","sources":["../../src/lifecycle/isolation-context.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typeorm-test-db",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Automated transactional lifecycle helpers for TypeORM tests",
5
5
  "license": "GPL-3.0-only",
6
6
  "main": "dist/index.js",
@@ -15,10 +15,17 @@
15
15
  "build": "tsc -p tsconfig.build.json",
16
16
  "clean": "rimraf dist",
17
17
  "prebuild": "pnpm clean",
18
- "test": "jest --ci --runInBand --forceExit --verbose --showSeed --coverage --config ./tests/jest.config.ts",
19
- "test:ci": "NODE_ENV=test jest --ci --runInBand --forceExit --verbose --showSeed --coverage --config ./tests/jest.config.ts",
18
+ "test": "jest --ci --maxWorkers=50% --verbose --showSeed --coverage --config ./tests/jest.config.ts",
19
+ "test:ci": "pnpm test",
20
+ "docker": "docker compose up -d",
20
21
  "lint": "eslint --fix",
21
- "release": "standard-version"
22
+ "release": "standard-version",
23
+ "test:mysql": "cross-env TEST_DB_TYPE=mysql pnpm test:ci",
24
+ "test:mariadb": "cross-env TEST_DB_TYPE=mariadb pnpm test:ci",
25
+ "test:postgres": "cross-env TEST_DB_TYPE=postgres pnpm test:ci",
26
+ "test:sqlite": "cross-env TEST_DB_TYPE=sqlite pnpm test:ci",
27
+ "test:better-sqlite3": "pnpm -s shx mkdir -p .tmp/better-sqlite && cross-env TEST_DB_TYPE=better-sqlite3 pnpm test:ci",
28
+ "test:all": "pnpm test:mysql && pnpm test:mariadb && pnpm test:postgres && pnpm test:sqlite && pnpm test:better-sqlite3"
22
29
  },
23
30
  "repository": {
24
31
  "type": "git",
@@ -39,7 +46,7 @@
39
46
  },
40
47
  "devDependencies": {
41
48
  "@jest/globals": "^30.1.2",
42
- "@jest/test-result": "^29.7.0",
49
+ "@jest/test-result": "^30.2.0",
43
50
  "@jest/test-sequencer": "^30.1.3",
44
51
  "@types/jest": "^30.0.0",
45
52
  "@types/node": "^24.5.2",
@@ -48,23 +55,25 @@
48
55
  "@typescript-eslint/eslint-plugin": "^7.0.0",
49
56
  "@typescript-eslint/parser": "^6.21.0",
50
57
  "better-sqlite3": "^9.4.3",
58
+ "cross-env": "7.0.3",
51
59
  "eslint": "^8.57.0",
52
- "eslint-config-prettier": "^9.1.0",
60
+ "eslint-config-prettier": "^10.1.8",
53
61
  "jest": "^30.1.3",
54
62
  "mysql2": "^3.11.2",
55
63
  "pg": "^8.11.5",
56
64
  "rimraf": "^5.0.5",
57
65
  "seedrandom": "^3.0.5",
66
+ "shx": "^0.4.0",
58
67
  "sqlite3": "^5.1.7",
59
68
  "standard-version": "^9.5.0",
60
69
  "ts-jest": "^29.1.1",
61
70
  "ts-node": "^10.9.2",
62
- "typeorm": "0.3.20",
71
+ "typeorm": "0.3.27",
63
72
  "typescript": "^5.3.3"
64
73
  },
65
74
  "packageManager": "pnpm@8.15.4",
66
75
  "volta": {
67
- "node": "20.16.0",
76
+ "node": "18.20.8",
68
77
  "pnpm": "8.15.4"
69
78
  }
70
79
  }
@@ -1,23 +0,0 @@
1
- import type { DataSource } from 'typeorm';
2
- export interface TransactionalTestLifecycle {
3
- readonly init: () => Promise<void>;
4
- readonly finish: () => Promise<void>;
5
- }
6
- export declare class TransactionalTestContext implements TransactionalTestLifecycle {
7
- private readonly dataSource;
8
- private originalManager;
9
- private queryRunner;
10
- private managerDescriptor;
11
- private originalDataSourceTransaction;
12
- private originalManagerTransaction;
13
- private patchedManager;
14
- constructor(dataSource: DataSource);
15
- readonly init: () => Promise<void>;
16
- readonly finish: () => Promise<void>;
17
- private restoreManager;
18
- private extractTransactionCallback;
19
- private isTransactionCallback;
20
- private patchTransactions;
21
- private restoreTransactions;
22
- }
23
- //# sourceMappingURL=TransactionalTestContext.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TransactionalTestContext.d.ts","sourceRoot":"","sources":["../../src/lifecycle/TransactionalTestContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA8B,MAAM,SAAS,CAAC;AAGtE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAID,qBAAa,wBAAyB,YAAW,0BAA0B;IACzE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,eAAe,CAA8B;IACrD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,iBAAiB,CAAmC;IAC5D,OAAO,CAAC,6BAA6B,CAA0C;IAC/E,OAAO,CAAC,0BAA0B,CAA6C;IAC/E,OAAO,CAAC,cAAc,CAA8B;gBAExC,UAAU,EAAE,UAAU;IAIlC,SAAgB,IAAI,QAAa,QAAQ,IAAI,CAAC,CAyB5C;IAEF,SAAgB,MAAM,QAAa,QAAQ,IAAI,CAAC,CAiB9C;IAEF,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,0BAA0B;IAWlC,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,mBAAmB;CAa5B"}
@@ -1,110 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TransactionalTestContext = void 0;
4
- const messages_1 = require("../constants/messages");
5
- class TransactionalTestContext {
6
- constructor(dataSource) {
7
- this.originalManager = null;
8
- this.queryRunner = null;
9
- this.managerDescriptor = null;
10
- this.originalDataSourceTransaction = null;
11
- this.originalManagerTransaction = null;
12
- this.patchedManager = null;
13
- this.init = async () => {
14
- if (!this.dataSource.isInitialized) {
15
- throw new Error(messages_1.errorMessages.dataSourceNotInitialized);
16
- }
17
- if (this.queryRunner !== null) {
18
- throw new Error(messages_1.errorMessages.transactionAlreadyStarted);
19
- }
20
- const queryRunner = this.dataSource.createQueryRunner();
21
- await queryRunner.connect();
22
- await queryRunner.startTransaction();
23
- this.originalManager = this.dataSource.manager;
24
- this.managerDescriptor = Object.getOwnPropertyDescriptor(this.dataSource, 'manager') ?? null;
25
- Object.defineProperty(this.dataSource, 'manager', {
26
- configurable: true,
27
- enumerable: true,
28
- get: () => queryRunner.manager
29
- });
30
- this.patchTransactions(queryRunner.manager);
31
- this.queryRunner = queryRunner;
32
- };
33
- this.finish = async () => {
34
- if (this.queryRunner === null) {
35
- return;
36
- }
37
- try {
38
- if (this.queryRunner.isTransactionActive) {
39
- await this.queryRunner.rollbackTransaction();
40
- }
41
- }
42
- finally {
43
- this.restoreTransactions();
44
- await this.queryRunner.release();
45
- this.restoreManager();
46
- this.queryRunner = null;
47
- this.originalManager = null;
48
- this.managerDescriptor = null;
49
- }
50
- };
51
- this.dataSource = dataSource;
52
- }
53
- restoreManager() {
54
- if (this.originalManager === null) {
55
- return;
56
- }
57
- const descriptor = this.managerDescriptor;
58
- if (descriptor !== null) {
59
- Object.defineProperty(this.dataSource, 'manager', descriptor);
60
- return;
61
- }
62
- Object.defineProperty(this.dataSource, 'manager', {
63
- configurable: true,
64
- enumerable: true,
65
- writable: true,
66
- value: this.originalManager
67
- });
68
- }
69
- extractTransactionCallback(args) {
70
- const [first, second] = args;
71
- if (this.isTransactionCallback(first)) {
72
- return first;
73
- }
74
- if (this.isTransactionCallback(second)) {
75
- return second;
76
- }
77
- throw new Error(messages_1.errorMessages.transactionCallbackMissing);
78
- }
79
- isTransactionCallback(candidate) {
80
- return typeof candidate === 'function';
81
- }
82
- patchTransactions(manager) {
83
- this.patchedManager = manager;
84
- this.originalDataSourceTransaction = this.dataSource.transaction.bind(this.dataSource);
85
- this.originalManagerTransaction = manager.transaction.bind(manager);
86
- const patched = async (...args) => {
87
- const callback = this.extractTransactionCallback(args);
88
- const result = callback(manager);
89
- return Promise.resolve(result);
90
- };
91
- const patchedWithIsolation = async (...args) => {
92
- return patched(...args);
93
- };
94
- this.dataSource.transaction = patchedWithIsolation;
95
- manager.transaction = patchedWithIsolation;
96
- }
97
- restoreTransactions() {
98
- if (this.originalDataSourceTransaction !== null) {
99
- this.dataSource.transaction = this.originalDataSourceTransaction;
100
- this.originalDataSourceTransaction = null;
101
- }
102
- if (this.patchedManager !== null && this.originalManagerTransaction !== null) {
103
- this.patchedManager.transaction = this.originalManagerTransaction;
104
- }
105
- this.patchedManager = null;
106
- this.originalManagerTransaction = null;
107
- }
108
- }
109
- exports.TransactionalTestContext = TransactionalTestContext;
110
- //# sourceMappingURL=TransactionalTestContext.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TransactionalTestContext.js","sourceRoot":"","sources":["../../src/lifecycle/TransactionalTestContext.ts"],"names":[],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- import type { DataSource } from 'typeorm';
2
- import { type TransactionalTestLifecycle } from './TransactionalTestContext';
3
- type HookCallback = () => Promise<void> | void;
4
- export interface TransactionalTestHooks {
5
- readonly beforeEach: (callback: HookCallback) => unknown;
6
- readonly afterEach: (callback: HookCallback) => unknown;
7
- }
8
- export interface RegisterTransactionalTestHooksOptions {
9
- readonly dataSource: DataSource;
10
- readonly hooks: TransactionalTestHooks;
11
- }
12
- export interface RegisteredTransactionalTestHooks {
13
- readonly lifecycle: TransactionalTestLifecycle;
14
- }
15
- export declare const registerTransactionalTestHooks: (options: RegisterTransactionalTestHooksOptions) => RegisteredTransactionalTestHooks;
16
- export {};
17
- //# sourceMappingURL=registerTransactionalHooks.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registerTransactionalHooks.d.ts","sourceRoot":"","sources":["../../src/lifecycle/registerTransactionalHooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAA4B,KAAK,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAEvG,KAAK,YAAY,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE/C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,OAAO,CAAC;IACzD,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,OAAO,CAAC;CACzD;AAED,MAAM,WAAW,qCAAqC;IACpD,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC;CACxC;AAED,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,SAAS,EAAE,0BAA0B,CAAC;CAChD;AAED,eAAO,MAAM,8BAA8B,YAChC,qCAAqC,KAC7C,gCAYF,CAAC"}
@@ -1,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerTransactionalTestHooks = void 0;
4
- const TransactionalTestContext_1 = require("./TransactionalTestContext");
5
- const registerTransactionalTestHooks = (options) => {
6
- const context = new TransactionalTestContext_1.TransactionalTestContext(options.dataSource);
7
- options.hooks.beforeEach(async () => {
8
- await context.init();
9
- });
10
- options.hooks.afterEach(async () => {
11
- await context.finish();
12
- });
13
- return { lifecycle: context };
14
- };
15
- exports.registerTransactionalTestHooks = registerTransactionalTestHooks;
16
- //# sourceMappingURL=registerTransactionalHooks.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registerTransactionalHooks.js","sourceRoot":"","sources":["../../src/lifecycle/registerTransactionalHooks.ts"],"names":[],"mappings":";;;AACA,yEAAuG;AAkBhG,MAAM,8BAA8B,GAAG,CAC5C,OAA8C,EACZ,EAAE;IACpC,MAAM,OAAO,GAAG,IAAI,mDAAwB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEjE,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE;QAClC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;QACjC,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC,CAAC;AAdW,QAAA,8BAA8B,kCAczC"}