fastypest 1.4.139 → 1.5.2
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.es.md +41 -0
- package/README.md +41 -0
- package/dist/core/fastypest.d.ts +13 -2
- package/dist/core/fastypest.js +168 -19
- package/dist/core/fastypest.js.map +1 -1
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +19 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/sql-script/queries/cockroachdb.json +1 -1
- package/dist/core/sql-script/queries/mysql.query.json +1 -1
- package/dist/core/sql-script/queries/postgres.query.json +1 -1
- package/dist/core/sql-script/sql-script.d.ts +1 -0
- package/dist/core/sql-script/sql-script.js +5 -0
- package/dist/core/sql-script/sql-script.js.map +1 -1
- package/dist/core/subscribers/change-tracker.subscriber.d.ts +10 -0
- package/dist/core/subscribers/change-tracker.subscriber.js +43 -0
- package/dist/core/subscribers/change-tracker.subscriber.js.map +1 -0
- package/dist/core/types.d.ts +9 -0
- package/dist/core/types.js +11 -0
- package/dist/core/types.js.map +1 -1
- package/dist/logging/constants.d.ts +30 -0
- package/dist/logging/constants.js +111 -0
- package/dist/logging/constants.js.map +1 -0
- package/dist/logging/index.d.ts +2 -0
- package/dist/logging/index.js +46 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/logger.d.ts +32 -0
- package/dist/logging/logger.js +371 -0
- package/dist/logging/logger.js.map +1 -0
- package/package.json +15 -11
package/README.es.md
CHANGED
|
@@ -49,6 +49,47 @@ afterEach(async () => {
|
|
|
49
49
|
});
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
## 🔄 Estrategias de detección de cambios
|
|
53
|
+
|
|
54
|
+
Por defecto Fastypest restaura todas las tablas. Puedes activar la detección de cambios mediante el subscriber de TypeORM para refrescar únicamente las tablas tocadas durante una prueba.
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
const fastypest = new Fastypest(connection, {
|
|
58
|
+
changeDetectionStrategy: ChangeDetectionStrategy.Subscriber,
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- `ChangeDetectionStrategy.None` mantiene el comportamiento anterior, truncando y restaurando cada tabla.
|
|
63
|
+
- `ChangeDetectionStrategy.Subscriber` escucha los eventos del subscriber de TypeORM (`insert`, `update`, `remove`) y restaura solo las tablas afectadas.
|
|
64
|
+
|
|
65
|
+
### Seguimiento manual y limitaciones
|
|
66
|
+
|
|
67
|
+
- Usa `fastypest.markTableAsChanged('tableName')` después de ejecutar SQL crudo para que la tabla se restaure junto con los cambios detectados por el subscriber.
|
|
68
|
+
- Si no se captura ningún evento del subscriber, Fastypest vuelve a restaurar toda la base de datos y garantiza que los cambios realizados únicamente con `connection.query()` se reviertan.
|
|
69
|
+
- Los subscribers de TypeORM no se activan con `.query(...)`, por lo que al habilitar la estrategia del subscriber es necesario trabajar con repositorios o query builders para disfrutar del seguimiento automático.
|
|
70
|
+
|
|
71
|
+
## 🔍 Registro
|
|
72
|
+
|
|
73
|
+
Fastypest incluye un logger basado en Winston que facilita seguir el flujo de inicialización y restauración.
|
|
74
|
+
|
|
75
|
+
- El registro está desactivado por defecto. Actívalo con `logging: true` o define una configuración personalizada.
|
|
76
|
+
- Usa `LoggingDetailLevel` para alternar entre el modo simple (errores, avisos, notices e info) y el modo detallado (todos los niveles).
|
|
77
|
+
- Combina `LoggingDetailLevel` con un array `levels` cuando necesites centrarte en niveles concretos de `LogLevel`.
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { Fastypest, LogLevel, LoggingDetailLevel } from "fastypest";
|
|
81
|
+
|
|
82
|
+
const fastypest = new Fastypest(connection, {
|
|
83
|
+
logging: {
|
|
84
|
+
enabled: true,
|
|
85
|
+
detail: LoggingDetailLevel.Detailed,
|
|
86
|
+
levels: [LogLevel.Info, LogLevel.Debug],
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Cuando defines `detail` y `levels` al mismo tiempo, Fastypest solo imprime la intersección de ambos filtros para mantener el registro enfocado en los eventos relevantes.
|
|
92
|
+
|
|
52
93
|
## ⚙️ Flujo de trabajo automatizado
|
|
53
94
|
|
|
54
95
|
Este proyecto usa un sistema CI/CD avanzado con GitHub Actions:
|
package/README.md
CHANGED
|
@@ -50,6 +50,47 @@ afterEach(async () => {
|
|
|
50
50
|
});
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
## 🔄 Change detection strategies
|
|
54
|
+
|
|
55
|
+
Fastypest restores every table by default. You can enable change detection driven by TypeORM subscribers to refresh only the tables touched during a test.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
const fastypest = new Fastypest(connection, {
|
|
59
|
+
changeDetectionStrategy: ChangeDetectionStrategy.Subscriber,
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- `ChangeDetectionStrategy.None` keeps the previous behaviour, truncating and restoring every table.
|
|
64
|
+
- `ChangeDetectionStrategy.Subscriber` listens to TypeORM subscriber events (`insert`, `update`, `remove`) and restores only the affected tables.
|
|
65
|
+
|
|
66
|
+
### Manual tracking and limitations
|
|
67
|
+
|
|
68
|
+
- Use `fastypest.markTableAsChanged('tableName')` after running raw SQL so the table is restored alongside subscriber-detected changes.
|
|
69
|
+
- When no subscriber event is captured Fastypest falls back to restoring the whole database, ensuring that changes executed exclusively through `connection.query()` are still reverted.
|
|
70
|
+
- TypeORM subscribers are not triggered by raw queries, so enabling the subscriber strategy requires using repositories or query builders for automatic tracking.
|
|
71
|
+
|
|
72
|
+
## 🔍 Logging
|
|
73
|
+
|
|
74
|
+
Fastypest ships with a Winston-based logger that helps you trace the initialization and restore workflow.
|
|
75
|
+
|
|
76
|
+
- Logging is disabled by default. Enable it with `logging: true` or provide a detailed configuration.
|
|
77
|
+
- Use `LoggingDetailLevel` to toggle between the simple preset (errors, warnings, notices, info) and the detailed preset (all levels).
|
|
78
|
+
- Combine `LoggingDetailLevel` with an explicit `levels` array when you need to focus on specific `LogLevel` entries.
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { Fastypest, LogLevel, LoggingDetailLevel } from "fastypest";
|
|
82
|
+
|
|
83
|
+
const fastypest = new Fastypest(connection, {
|
|
84
|
+
logging: {
|
|
85
|
+
enabled: true,
|
|
86
|
+
detail: LoggingDetailLevel.Detailed,
|
|
87
|
+
levels: [LogLevel.Info, LogLevel.Debug],
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
When both `detail` and `levels` are provided, Fastypest only prints the intersection of the two filters, keeping the output focused on the events you care about.
|
|
93
|
+
|
|
53
94
|
## ⚙️ Automated Workflow
|
|
54
95
|
|
|
55
96
|
This project leverages a sophisticated CI/CD setup using GitHub Actions:
|
package/dist/core/fastypest.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { Connection, DataSource, EntityManager } from "typeorm";
|
|
2
2
|
import { SQLScript } from "./sql-script";
|
|
3
|
-
import type
|
|
3
|
+
import { type FastypestOptions, type Manager } from "./types";
|
|
4
4
|
export declare class Fastypest extends SQLScript {
|
|
5
5
|
private manager;
|
|
6
6
|
private tables;
|
|
7
7
|
private tablesWithAutoIncrement;
|
|
8
8
|
private restoreInOder;
|
|
9
|
-
|
|
9
|
+
private readonly options;
|
|
10
|
+
private readonly changedTables;
|
|
11
|
+
private readonly logger;
|
|
12
|
+
constructor(connection: DataSource | Connection, options?: FastypestOptions);
|
|
10
13
|
init(): Promise<void>;
|
|
11
14
|
private createTempTable;
|
|
12
15
|
private detectTablesWithAutoIncrement;
|
|
@@ -23,4 +26,12 @@ export declare class Fastypest extends SQLScript {
|
|
|
23
26
|
private restoreOrder;
|
|
24
27
|
private recreateData;
|
|
25
28
|
private resetAutoIncrementColumns;
|
|
29
|
+
private registerSubscriber;
|
|
30
|
+
private isDataSource;
|
|
31
|
+
private getSubscriberCollection;
|
|
32
|
+
private bindSubscriber;
|
|
33
|
+
private shouldTrackChanges;
|
|
34
|
+
private getTablesForRestore;
|
|
35
|
+
markTableAsChanged(tableName: string): void;
|
|
36
|
+
private resolveLoggingConfiguration;
|
|
26
37
|
}
|
package/dist/core/fastypest.js
CHANGED
|
@@ -8,8 +8,12 @@ Object.defineProperty(exports, "Fastypest", {
|
|
|
8
8
|
return Fastypest;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
+
const _typeorm = require("typeorm");
|
|
11
12
|
const _config = require("./config");
|
|
12
13
|
const _sqlscript = require("./sql-script");
|
|
14
|
+
const _changetrackersubscriber = require("./subscribers/change-tracker.subscriber");
|
|
15
|
+
const _types = require("./types");
|
|
16
|
+
const _logging = require("../logging");
|
|
13
17
|
function _define_property(obj, key, value) {
|
|
14
18
|
if (key in obj) {
|
|
15
19
|
Object.defineProperty(obj, key, {
|
|
@@ -23,8 +27,11 @@ function _define_property(obj, key, value) {
|
|
|
23
27
|
}
|
|
24
28
|
return obj;
|
|
25
29
|
}
|
|
30
|
+
const PROGRESS_OFFSET = 1;
|
|
26
31
|
class Fastypest extends _sqlscript.SQLScript {
|
|
27
32
|
async init() {
|
|
33
|
+
const timer = this.logger.timer("Initialization");
|
|
34
|
+
this.logger.verbose("🚀 Initialization started", `Database ${this.getType()}`);
|
|
28
35
|
await this.manager.transaction(async (em)=>{
|
|
29
36
|
await this.detectTables(em);
|
|
30
37
|
await this.calculateDependencyTables(em);
|
|
@@ -36,24 +43,32 @@ class Fastypest extends _sqlscript.SQLScript {
|
|
|
36
43
|
this.detectTablesWithAutoIncrement(em, tables)
|
|
37
44
|
]);
|
|
38
45
|
});
|
|
46
|
+
timer.end("✅ Initialization completed", _logging.LogLevel.Info, `Tables ${this.tables.size}`, `Tables with auto increment ${this.tablesWithAutoIncrement.size}`);
|
|
39
47
|
}
|
|
40
48
|
async createTempTable(em, tables) {
|
|
41
|
-
|
|
49
|
+
const totalTables = tables.length;
|
|
50
|
+
await Promise.all(tables.map(async (tableName, index)=>{
|
|
51
|
+
await this.execQuery(em, "dropTempTable", {
|
|
52
|
+
tableName
|
|
53
|
+
});
|
|
42
54
|
await this.execQuery(em, "createTempTable", {
|
|
43
55
|
tableName
|
|
44
56
|
});
|
|
57
|
+
this.logger.debug("🧪 Temporary table prepared", `Table ${tableName}`, `Progress ${index + PROGRESS_OFFSET}/${totalTables}`);
|
|
45
58
|
}));
|
|
46
59
|
}
|
|
47
60
|
async detectTablesWithAutoIncrement(em, tables) {
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
const totalTables = tables.length;
|
|
62
|
+
for (const [index, tableName] of tables.entries()){
|
|
63
|
+
await this.processTable(em, tableName, index + PROGRESS_OFFSET, totalTables);
|
|
50
64
|
}
|
|
65
|
+
this.logger.debug("📊 Auto increment analysis completed", `Tables with auto increment ${this.tablesWithAutoIncrement.size}`);
|
|
51
66
|
}
|
|
52
|
-
async processTable(em, tableName) {
|
|
67
|
+
async processTable(em, tableName, position, total) {
|
|
53
68
|
const columns = await this.getColumnsWithAutoIncrement(em, tableName);
|
|
54
69
|
if (!columns) return;
|
|
55
70
|
for (const column of columns){
|
|
56
|
-
await this.processColumn(em, tableName, column);
|
|
71
|
+
await this.processColumn(em, tableName, column, position, total);
|
|
57
72
|
}
|
|
58
73
|
}
|
|
59
74
|
async getColumnsWithAutoIncrement(em, tableName) {
|
|
@@ -62,7 +77,7 @@ class Fastypest extends _sqlscript.SQLScript {
|
|
|
62
77
|
});
|
|
63
78
|
return Array.isArray(columns) ? columns : null;
|
|
64
79
|
}
|
|
65
|
-
async processColumn(em, tableName, column) {
|
|
80
|
+
async processColumn(em, tableName, column, position, total) {
|
|
66
81
|
const stat = await this.getMaxColumnIndex(em, tableName, column.column_name);
|
|
67
82
|
const sequenceName = this.getSequenceName(column.column_default);
|
|
68
83
|
if (!sequenceName) return;
|
|
@@ -72,6 +87,7 @@ class Fastypest extends _sqlscript.SQLScript {
|
|
|
72
87
|
sequenceName,
|
|
73
88
|
index: String(index + (_config.INDEX_OFFSET_CONFIG[this.getType()] ?? 0))
|
|
74
89
|
});
|
|
90
|
+
this.logger.debug("🔁 Auto increment column processed", `Table ${tableName}`, `Column ${column.column_name}`, `Sequence ${sequenceName}`, `Progress ${position}/${total}`);
|
|
75
91
|
}
|
|
76
92
|
async getMaxColumnIndex(em, tableName, columnName) {
|
|
77
93
|
const [stat] = await this.execQuery(em, "getMaxColumnIndex", {
|
|
@@ -90,12 +106,20 @@ class Fastypest extends _sqlscript.SQLScript {
|
|
|
90
106
|
this.tablesWithAutoIncrement.get(tableName)?.push(data);
|
|
91
107
|
}
|
|
92
108
|
async restoreData() {
|
|
109
|
+
const tablesToRestore = this.getTablesForRestore();
|
|
110
|
+
if (this.shouldTrackChanges() && this.changedTables.size === 0) {
|
|
111
|
+
this.logger.debug("🕊️ No tracked table changes detected", `Tables ${tablesToRestore.length}`);
|
|
112
|
+
}
|
|
113
|
+
const timer = this.logger.timer("Restore process");
|
|
114
|
+
const changeSummary = this.shouldTrackChanges() ? `Tracked changes ${this.changedTables.size}` : undefined;
|
|
115
|
+
this.logger.verbose("🛠️ Restore process started", `Tables selected ${tablesToRestore.length}`, changeSummary);
|
|
93
116
|
await this.manager.transaction(async (em)=>{
|
|
94
117
|
const { foreignKey, restoreOrder } = await this.restoreManager(em);
|
|
95
118
|
await foreignKey.disable();
|
|
96
119
|
await restoreOrder();
|
|
97
120
|
await foreignKey.enable();
|
|
98
121
|
});
|
|
122
|
+
timer.end("🎉 Restore process completed", _logging.LogLevel.Info, `Tables restored ${tablesToRestore.length}`);
|
|
99
123
|
}
|
|
100
124
|
async restoreManager(em) {
|
|
101
125
|
if (this.tables.size === 0) {
|
|
@@ -114,50 +138,75 @@ class Fastypest extends _sqlscript.SQLScript {
|
|
|
114
138
|
"mysql"
|
|
115
139
|
];
|
|
116
140
|
if (typesWithForeignKey.includes(this.getType())) {
|
|
117
|
-
manager.foreignKey.disable = async ()=>
|
|
118
|
-
|
|
141
|
+
manager.foreignKey.disable = async ()=>{
|
|
142
|
+
this.logger.debug("🚧 Foreign keys disabled", `Database ${this.getType()}`);
|
|
143
|
+
await this.execQuery(em, "foreignKey.disable");
|
|
144
|
+
};
|
|
145
|
+
manager.foreignKey.enable = async ()=>{
|
|
146
|
+
await this.execQuery(em, "foreignKey.enable");
|
|
147
|
+
this.logger.debug("🆗 Foreign keys enabled", `Database ${this.getType()}`);
|
|
148
|
+
};
|
|
119
149
|
}
|
|
120
150
|
manager.restoreOrder = ()=>this.restoreOrder(em);
|
|
121
151
|
return manager;
|
|
122
152
|
}
|
|
123
153
|
async calculateDependencyTables(em) {
|
|
154
|
+
const timer = this.logger.timer("Dependency planning");
|
|
155
|
+
this.logger.debug("🧭 Calculating dependency order for restore");
|
|
124
156
|
const dependencyTree = await this.execQuery(em, "dependencyTree");
|
|
125
157
|
if (!dependencyTree.length) {
|
|
126
158
|
this.restoreInOder = false;
|
|
159
|
+
timer.end("🧭 Dependency order calculated", _logging.LogLevel.Debug, "Mode parallel", `Tables ${this.tables.size}`);
|
|
127
160
|
return;
|
|
128
161
|
}
|
|
129
162
|
const sortedTables = new Set(dependencyTree.map((row)=>row.table_name));
|
|
130
163
|
this.tables.clear();
|
|
131
164
|
this.tables = sortedTables;
|
|
132
165
|
this.restoreInOder = true;
|
|
166
|
+
timer.end("🧭 Dependency order calculated", _logging.LogLevel.Debug, "Mode ordered", `Tables ${this.tables.size}`);
|
|
133
167
|
}
|
|
134
168
|
async detectTables(em) {
|
|
169
|
+
const timer = this.logger.timer("Table discovery");
|
|
170
|
+
this.logger.debug("🗂️ Discovering tables from database");
|
|
135
171
|
const tables = await this.execQuery(em, "getTables");
|
|
136
|
-
if (!tables)
|
|
172
|
+
if (!tables) {
|
|
173
|
+
timer.end("🗂️ Table discovery completed", _logging.LogLevel.Debug, `Tables ${this.tables.size}`);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
137
176
|
tables.forEach((row)=>{
|
|
138
177
|
this.tables.add(row.name);
|
|
139
178
|
});
|
|
179
|
+
timer.end("🗂️ Table discovery completed", _logging.LogLevel.Debug, `Tables ${this.tables.size}`);
|
|
140
180
|
}
|
|
141
181
|
async restoreOrder(em) {
|
|
182
|
+
const tables = this.getTablesForRestore();
|
|
183
|
+
const totalTables = tables.length;
|
|
142
184
|
if (this.restoreInOder) {
|
|
143
|
-
|
|
144
|
-
|
|
185
|
+
this.logger.verbose("🧱 Restore mode ordered", `Tables ${totalTables}`);
|
|
186
|
+
for (const [index, tableName] of tables.entries()){
|
|
187
|
+
await this.recreateData(em, tableName, index + PROGRESS_OFFSET, totalTables);
|
|
145
188
|
}
|
|
146
|
-
|
|
189
|
+
} else {
|
|
190
|
+
this.logger.verbose("🧱 Restore mode parallel", `Tables ${totalTables}`);
|
|
191
|
+
await Promise.all(tables.map((tableName, index)=>this.recreateData(em, tableName, index + PROGRESS_OFFSET, totalTables)));
|
|
192
|
+
}
|
|
193
|
+
if (this.shouldTrackChanges()) {
|
|
194
|
+
this.changedTables.clear();
|
|
147
195
|
}
|
|
148
|
-
const tables = [
|
|
149
|
-
...this.tables
|
|
150
|
-
];
|
|
151
|
-
await Promise.all(tables.map((tableName)=>this.recreateData(em, tableName)));
|
|
152
196
|
}
|
|
153
|
-
async recreateData(em, tableName) {
|
|
197
|
+
async recreateData(em, tableName, position, total) {
|
|
198
|
+
const timer = this.logger.timer(`Restore ${tableName}`);
|
|
199
|
+
this.logger.debug("📥 Restoring table", `Table ${tableName}`, `Progress ${position}/${total}`);
|
|
154
200
|
await this.execQuery(em, "truncateTable", {
|
|
155
201
|
tableName
|
|
156
202
|
});
|
|
203
|
+
timer.mark("🧹 Table truncated", _logging.LogLevel.Debug, `Table ${tableName}`, `Progress ${position}/${total}`);
|
|
157
204
|
await this.execQuery(em, "restoreData", {
|
|
158
205
|
tableName
|
|
159
206
|
});
|
|
207
|
+
timer.mark("📦 Table data restored", _logging.LogLevel.Debug, `Table ${tableName}`, `Progress ${position}/${total}`);
|
|
160
208
|
await this.resetAutoIncrementColumns(em, tableName);
|
|
209
|
+
timer.end("✅ Table restored", _logging.LogLevel.Info, `Table ${tableName}`, `Progress ${position}/${total}`);
|
|
161
210
|
}
|
|
162
211
|
async resetAutoIncrementColumns(em, tableName) {
|
|
163
212
|
const tables = this.tablesWithAutoIncrement.get(tableName);
|
|
@@ -169,11 +218,111 @@ class Fastypest extends _sqlscript.SQLScript {
|
|
|
169
218
|
sequenceName,
|
|
170
219
|
index
|
|
171
220
|
});
|
|
221
|
+
this.logger.debug("♻️ Auto increment column reset", `Table ${tableName}`, `Column ${column}`, `Sequence ${sequenceName}`, `Next value ${index}`);
|
|
172
222
|
}
|
|
173
223
|
}
|
|
174
|
-
|
|
175
|
-
|
|
224
|
+
registerSubscriber(connection) {
|
|
225
|
+
const subscriber = new _changetrackersubscriber.ChangeTrackerSubscriber((tableName)=>{
|
|
226
|
+
this.markTableAsChanged(tableName);
|
|
227
|
+
});
|
|
228
|
+
this.getSubscriberCollection(connection).push(subscriber);
|
|
229
|
+
this.bindSubscriber(subscriber, connection);
|
|
230
|
+
this.logger.info("📡 Change tracking subscriber registered", `Database ${this.getType()}`);
|
|
231
|
+
}
|
|
232
|
+
isDataSource(connection) {
|
|
233
|
+
return connection instanceof _typeorm.DataSource;
|
|
234
|
+
}
|
|
235
|
+
getSubscriberCollection(connection) {
|
|
236
|
+
return connection.subscribers;
|
|
237
|
+
}
|
|
238
|
+
bindSubscriber(subscriber, connection) {
|
|
239
|
+
const lifecycle = subscriber;
|
|
240
|
+
if (this.isDataSource(connection)) {
|
|
241
|
+
lifecycle.setDataSource?.(connection);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
lifecycle.setConnection?.(connection);
|
|
245
|
+
}
|
|
246
|
+
shouldTrackChanges() {
|
|
247
|
+
return this.options.changeDetectionStrategy === _types.ChangeDetectionStrategy.Subscriber;
|
|
248
|
+
}
|
|
249
|
+
getTablesForRestore() {
|
|
250
|
+
const tables = [
|
|
251
|
+
...this.tables
|
|
252
|
+
];
|
|
253
|
+
if (!this.shouldTrackChanges()) {
|
|
254
|
+
return tables;
|
|
255
|
+
}
|
|
256
|
+
if (this.changedTables.size === 0) {
|
|
257
|
+
return tables;
|
|
258
|
+
}
|
|
259
|
+
const changed = new Set(this.changedTables);
|
|
260
|
+
const filtered = tables.filter((table)=>changed.has(table));
|
|
261
|
+
if (filtered.length === 0) {
|
|
262
|
+
return tables;
|
|
263
|
+
}
|
|
264
|
+
this.logger.debug("🗜️ Filtering tables by tracked changes", `Matched tables ${filtered.length}`, `Total tables ${tables.length}`);
|
|
265
|
+
return filtered;
|
|
266
|
+
}
|
|
267
|
+
markTableAsChanged(tableName) {
|
|
268
|
+
if (!this.shouldTrackChanges()) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const wasTracked = this.changedTables.has(tableName);
|
|
272
|
+
this.changedTables.add(tableName);
|
|
273
|
+
if (!wasTracked) {
|
|
274
|
+
this.logger.debug("🔎 Table change detected", `Table ${tableName}`, `Tracked tables ${this.changedTables.size}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
resolveLoggingConfiguration(logging) {
|
|
278
|
+
if (typeof logging === "boolean") {
|
|
279
|
+
return {
|
|
280
|
+
enabled: logging
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
if (!logging) {
|
|
284
|
+
return undefined;
|
|
285
|
+
}
|
|
286
|
+
if (logging.enabled === undefined) {
|
|
287
|
+
return {
|
|
288
|
+
...logging,
|
|
289
|
+
enabled: true
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
return logging;
|
|
293
|
+
}
|
|
294
|
+
constructor(connection, options){
|
|
295
|
+
super(connection.options.type), _define_property(this, "manager", void 0), _define_property(this, "tables", new Set()), _define_property(this, "tablesWithAutoIncrement", new Map()), _define_property(this, "restoreInOder", false), _define_property(this, "options", void 0), _define_property(this, "changedTables", new Set()), _define_property(this, "logger", void 0);
|
|
296
|
+
const loggingConfiguration = this.resolveLoggingConfiguration(options?.logging);
|
|
297
|
+
const resolvedLogging = (0, _logging.configureLogging)(loggingConfiguration);
|
|
298
|
+
this.logger = (0, _logging.createScopedLogger)("Fastypest");
|
|
176
299
|
this.manager = connection.manager;
|
|
300
|
+
this.options = {
|
|
301
|
+
changeDetectionStrategy: options?.changeDetectionStrategy ?? _types.ChangeDetectionStrategy.None
|
|
302
|
+
};
|
|
303
|
+
const detailLevels = resolvedLogging.detail !== undefined ? _logging.LOGGING_DETAIL_LEVELS[resolvedLogging.detail] : undefined;
|
|
304
|
+
const customLevels = resolvedLogging.levels && resolvedLogging.levels.length > 0 ? resolvedLogging.levels : undefined;
|
|
305
|
+
const activeLevels = detailLevels && customLevels ? customLevels.filter((level)=>detailLevels.includes(level)) : detailLevels ?? customLevels ?? _logging.LOGGING_LEVEL_SEQUENCE;
|
|
306
|
+
const activeLevelLabels = activeLevels.map((level)=>_logging.LOGGING_LEVEL_LABELS[level]);
|
|
307
|
+
const detailText = resolvedLogging.detail !== undefined ? `Style ${resolvedLogging.detail === _logging.LoggingDetailLevel.Simple ? "Simple" : "Detailed"}` : undefined;
|
|
308
|
+
const customLevelText = customLevels ? `Selected levels ${customLevels.map((level)=>_logging.LOGGING_LEVEL_LABELS[level]).join(", ")}` : undefined;
|
|
309
|
+
const activeLevelText = detailLevels && customLevels && activeLevels.length === 0 ? "Active levels none" : `Active levels ${activeLevelLabels.join(", ")}`;
|
|
310
|
+
const loggingDetails = [
|
|
311
|
+
detailText,
|
|
312
|
+
customLevelText,
|
|
313
|
+
activeLevelText,
|
|
314
|
+
`Database ${this.getType()}`,
|
|
315
|
+
`Change detection ${this.options.changeDetectionStrategy}`
|
|
316
|
+
].filter((entry)=>Boolean(entry));
|
|
317
|
+
if (resolvedLogging.enabled) {
|
|
318
|
+
this.logger.log("🟢 Logging enabled", ...loggingDetails);
|
|
319
|
+
} else {
|
|
320
|
+
this.logger.warn("⚪️ Logging disabled", ...loggingDetails);
|
|
321
|
+
}
|
|
322
|
+
if (this.options.changeDetectionStrategy === _types.ChangeDetectionStrategy.Subscriber) {
|
|
323
|
+
this.logger.info("🛰️ Change detection strategy enabled");
|
|
324
|
+
this.registerSubscriber(connection);
|
|
325
|
+
}
|
|
177
326
|
}
|
|
178
327
|
}
|
|
179
328
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/fastypest.ts"],"sourcesContent":["import { Connection, DataSource, EntityManager, Table } from \"typeorm\";\nimport { INDEX_OFFSET_CONFIG } from \"./config\";\nimport { SQLScript } from \"./sql-script\";\nimport type {\n ColumnStat,\n ColumnsWithAutoIncrement,\n DBType,\n DependencyTreeQueryOut,\n IncrementDetail,\n Manager,\n} from \"./types\";\n\nexport class Fastypest extends SQLScript {\n private manager: EntityManager;\n private tables: Set<string> = new Set();\n private tablesWithAutoIncrement: Map<string, IncrementDetail[]> = new Map();\n private restoreInOder: boolean = false;\n\n constructor(connection: DataSource | Connection) {\n super(connection.options.type);\n this.manager = connection.manager;\n }\n\n public async init(): Promise<void> {\n await this.manager.transaction(async (em: EntityManager) => {\n await this.detectTables(em);\n await this.calculateDependencyTables(em);\n const tables = [...this.tables];\n await Promise.all([\n this.createTempTable(em, tables),\n this.detectTablesWithAutoIncrement(em, tables),\n ]);\n });\n }\n\n private async createTempTable(\n em: EntityManager,\n tables: string[]\n ): Promise<void> {\n await Promise.all(\n tables.map(async (tableName) => {\n await this.execQuery(em, \"createTempTable\", { tableName });\n })\n );\n }\n\n private async detectTablesWithAutoIncrement(\n em: EntityManager,\n tables: string[]\n ): Promise<void> {\n for (const tableName of tables) {\n await this.processTable(em, tableName);\n }\n }\n\n private async processTable(\n em: EntityManager,\n tableName: string\n ): Promise<void> {\n const columns = await this.getColumnsWithAutoIncrement(em, tableName);\n if (!columns) return;\n\n for (const column of columns) {\n await this.processColumn(em, tableName, column);\n }\n }\n\n private async getColumnsWithAutoIncrement(\n em: EntityManager,\n tableName: string\n ): Promise<ColumnsWithAutoIncrement[] | null> {\n const columns = await this.execQuery<ColumnsWithAutoIncrement>(\n em,\n \"getColumnsWithAutoIncrement\",\n { tableName }\n );\n return Array.isArray(columns) ? columns : null;\n }\n\n private async processColumn(\n em: EntityManager,\n tableName: string,\n column: ColumnsWithAutoIncrement\n ): Promise<void> {\n const stat = await this.getMaxColumnIndex(\n em,\n tableName,\n column.column_name\n );\n const sequenceName = this.getSequenceName(column.column_default);\n if (!sequenceName) return;\n\n const index = Number(stat?.maxindex) || 0;\n this.updateTablesWithAutoIncrement(tableName, {\n column: column.column_name,\n sequenceName,\n index: String(index + (INDEX_OFFSET_CONFIG[this.getType()] ?? 0)),\n });\n }\n\n private async getMaxColumnIndex(\n em: EntityManager,\n tableName: string,\n columnName: string\n ): Promise<ColumnStat | null> {\n const [stat] = await this.execQuery<ColumnStat>(em, \"getMaxColumnIndex\", {\n tableName,\n column_name: columnName,\n });\n return stat || null;\n }\n\n private getSequenceName(columnDefault: string): string | null {\n return columnDefault.match(/'([^']+)'/)?.[1] || null;\n }\n\n private updateTablesWithAutoIncrement(\n tableName: string,\n data: { column: string; sequenceName: string; index: string }\n ): void {\n if (!this.tablesWithAutoIncrement.has(tableName)) {\n this.tablesWithAutoIncrement.set(tableName, []);\n }\n\n this.tablesWithAutoIncrement.get(tableName)?.push(data);\n }\n\n public async restoreData(): Promise<void> {\n await this.manager.transaction(async (em: EntityManager) => {\n const { foreignKey, restoreOrder } = await this.restoreManager(em);\n await foreignKey.disable();\n await restoreOrder();\n await foreignKey.enable();\n });\n }\n\n protected async restoreManager(em: EntityManager): Promise<Manager> {\n if (this.tables.size === 0) {\n await this.detectTables(em);\n }\n\n const manager: Manager = {\n foreignKey: {\n disable: async () => Promise.resolve(),\n enable: async () => Promise.resolve(),\n },\n restoreOrder: async () => Promise.resolve(),\n };\n\n const typesWithForeignKey: DBType[] = [\"postgres\", \"mariadb\", \"mysql\"];\n if (typesWithForeignKey.includes(this.getType())) {\n manager.foreignKey.disable = async (): Promise<void> =>\n this.execQuery(em, \"foreignKey.disable\");\n manager.foreignKey.enable = async (): Promise<void> =>\n this.execQuery(em, \"foreignKey.enable\");\n }\n\n manager.restoreOrder = (): Promise<void> => this.restoreOrder(em);\n\n return manager;\n }\n\n private async calculateDependencyTables(em: EntityManager): Promise<void> {\n const dependencyTree = await this.execQuery<DependencyTreeQueryOut>(\n em,\n \"dependencyTree\"\n );\n\n if (!dependencyTree.length) {\n this.restoreInOder = false;\n return;\n }\n\n const sortedTables = new Set(dependencyTree.map((row) => row.table_name));\n this.tables.clear();\n this.tables = sortedTables;\n this.restoreInOder = true;\n }\n\n private async detectTables(em: EntityManager): Promise<void> {\n const tables = await this.execQuery<Table>(em, \"getTables\");\n if(!tables) return;\n\n tables.forEach((row) => {\n this.tables.add(row.name);\n });\n }\n\n private async restoreOrder(em: EntityManager): Promise<void> {\n if (this.restoreInOder) {\n for (const tableName of this.tables) {\n await this.recreateData(em, tableName);\n }\n\n return;\n }\n\n const tables = [...this.tables];\n await Promise.all(\n tables.map((tableName) => this.recreateData(em, tableName))\n );\n }\n\n private async recreateData(\n em: EntityManager,\n tableName: string\n ): Promise<void> {\n await this.execQuery(em, \"truncateTable\", { tableName });\n await this.execQuery(em, \"restoreData\", { tableName });\n await this.resetAutoIncrementColumns(em, tableName);\n }\n\n private async resetAutoIncrementColumns(\n em: EntityManager,\n tableName: string\n ): Promise<void> {\n const tables = this.tablesWithAutoIncrement.get(tableName);\n if (!tables) return;\n\n for (const { column, sequenceName, index } of tables) {\n await this.execQuery(em, \"resetAutoIncrementColumn\", {\n tableName,\n column,\n sequenceName,\n index,\n });\n }\n }\n}\n"],"names":["Fastypest","SQLScript","init","manager","transaction","em","detectTables","calculateDependencyTables","tables","Promise","all","createTempTable","detectTablesWithAutoIncrement","map","tableName","execQuery","processTable","columns","getColumnsWithAutoIncrement","column","processColumn","Array","isArray","stat","getMaxColumnIndex","column_name","sequenceName","getSequenceName","column_default","index","Number","maxindex","updateTablesWithAutoIncrement","String","INDEX_OFFSET_CONFIG","getType","columnName","columnDefault","match","data","tablesWithAutoIncrement","has","set","get","push","restoreData","foreignKey","restoreOrder","restoreManager","disable","enable","size","resolve","typesWithForeignKey","includes","dependencyTree","length","restoreInOder","sortedTables","Set","row","table_name","clear","forEach","add","name","recreateData","resetAutoIncrementColumns","connection","options","type","Map"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/core/fastypest.ts"],"sourcesContent":["import {\n Connection,\n DataSource,\n EntityManager,\n EntitySubscriberInterface,\n Table,\n} from \"typeorm\";\nimport { INDEX_OFFSET_CONFIG } from \"./config\";\nimport { SQLScript } from \"./sql-script\";\nimport { ChangeTrackerSubscriber } from \"./subscribers/change-tracker.subscriber\";\nimport {\n ChangeDetectionStrategy,\n type ColumnStat,\n type ColumnsWithAutoIncrement,\n type DBType,\n type DependencyTreeQueryOut,\n type FastypestOptions,\n type IncrementDetail,\n type Manager,\n} from \"./types\";\nimport {\n configureLogging,\n createScopedLogger,\n LogLevel,\n LOGGING_DETAIL_LEVELS,\n LOGGING_LEVEL_LABELS,\n LOGGING_LEVEL_SEQUENCE,\n LoggingDetailLevel,\n} from \"../logging\";\nimport type { LoggingOptions, ScopedLogger } from \"../logging\";\n\nconst PROGRESS_OFFSET = 1;\n\nexport class Fastypest extends SQLScript {\n private manager: EntityManager;\n private tables: Set<string> = new Set();\n private tablesWithAutoIncrement: Map<string, IncrementDetail[]> = new Map();\n private restoreInOder: boolean = false;\n private readonly options: Required<Omit<FastypestOptions, \"logging\">>;\n private readonly changedTables: Set<string> = new Set();\n private readonly logger: ScopedLogger;\n\n constructor(\n connection: DataSource | Connection,\n options?: FastypestOptions\n ) {\n super(connection.options.type);\n const loggingConfiguration = this.resolveLoggingConfiguration(options?.logging);\n const resolvedLogging = configureLogging(loggingConfiguration);\n this.logger = createScopedLogger(\"Fastypest\");\n this.manager = connection.manager;\n this.options = {\n changeDetectionStrategy:\n options?.changeDetectionStrategy ?? ChangeDetectionStrategy.None,\n };\n const detailLevels =\n resolvedLogging.detail !== undefined\n ? LOGGING_DETAIL_LEVELS[resolvedLogging.detail]\n : undefined;\n const customLevels =\n resolvedLogging.levels && resolvedLogging.levels.length > 0\n ? resolvedLogging.levels\n : undefined;\n const activeLevels = detailLevels && customLevels\n ? customLevels.filter((level) => detailLevels.includes(level))\n : detailLevels ?? customLevels ?? LOGGING_LEVEL_SEQUENCE;\n const activeLevelLabels = activeLevels.map(\n (level) => LOGGING_LEVEL_LABELS[level]\n );\n const detailText =\n resolvedLogging.detail !== undefined\n ? `Style ${\n resolvedLogging.detail === LoggingDetailLevel.Simple\n ? \"Simple\"\n : \"Detailed\"\n }`\n : undefined;\n const customLevelText = customLevels\n ? `Selected levels ${customLevels\n .map((level) => LOGGING_LEVEL_LABELS[level])\n .join(\", \")}`\n : undefined;\n const activeLevelText =\n detailLevels && customLevels && activeLevels.length === 0\n ? \"Active levels none\"\n : `Active levels ${activeLevelLabels.join(\", \")}`;\n const loggingDetails = [\n detailText,\n customLevelText,\n activeLevelText,\n `Database ${this.getType()}`,\n `Change detection ${this.options.changeDetectionStrategy}`,\n ].filter((entry): entry is string => Boolean(entry));\n if (resolvedLogging.enabled) {\n this.logger.log(\"🟢 Logging enabled\", ...loggingDetails);\n } else {\n this.logger.warn(\"⚪️ Logging disabled\", ...loggingDetails);\n }\n if (\n this.options.changeDetectionStrategy ===\n ChangeDetectionStrategy.Subscriber\n ) {\n this.logger.info(\"🛰️ Change detection strategy enabled\");\n this.registerSubscriber(connection);\n }\n }\n\n public async init(): Promise<void> {\n const timer = this.logger.timer(\"Initialization\");\n this.logger.verbose(\"🚀 Initialization started\", `Database ${this.getType()}`);\n await this.manager.transaction(async (em: EntityManager) => {\n await this.detectTables(em);\n await this.calculateDependencyTables(em);\n const tables = [...this.tables];\n await Promise.all([\n this.createTempTable(em, tables),\n this.detectTablesWithAutoIncrement(em, tables),\n ]);\n });\n timer.end(\n \"✅ Initialization completed\",\n LogLevel.Info,\n `Tables ${this.tables.size}`,\n `Tables with auto increment ${this.tablesWithAutoIncrement.size}`\n );\n }\n\n private async createTempTable(\n em: EntityManager,\n tables: string[]\n ): Promise<void> {\n const totalTables = tables.length;\n await Promise.all(\n tables.map(async (tableName, index) => {\n await this.execQuery(em, \"dropTempTable\", { tableName });\n await this.execQuery(em, \"createTempTable\", { tableName });\n this.logger.debug(\n \"🧪 Temporary table prepared\",\n `Table ${tableName}`,\n `Progress ${index + PROGRESS_OFFSET}/${totalTables}`\n );\n })\n );\n }\n\n private async detectTablesWithAutoIncrement(\n em: EntityManager,\n tables: string[]\n ): Promise<void> {\n const totalTables = tables.length;\n for (const [index, tableName] of tables.entries()) {\n await this.processTable(em, tableName, index + PROGRESS_OFFSET, totalTables);\n }\n this.logger.debug(\n \"📊 Auto increment analysis completed\",\n `Tables with auto increment ${this.tablesWithAutoIncrement.size}`\n );\n }\n\n private async processTable(\n em: EntityManager,\n tableName: string,\n position: number,\n total: number\n ): Promise<void> {\n const columns = await this.getColumnsWithAutoIncrement(em, tableName);\n if (!columns) return;\n\n for (const column of columns) {\n await this.processColumn(em, tableName, column, position, total);\n }\n }\n\n private async getColumnsWithAutoIncrement(\n em: EntityManager,\n tableName: string\n ): Promise<ColumnsWithAutoIncrement[] | null> {\n const columns = await this.execQuery<ColumnsWithAutoIncrement>(\n em,\n \"getColumnsWithAutoIncrement\",\n { tableName }\n );\n return Array.isArray(columns) ? columns : null;\n }\n\n private async processColumn(\n em: EntityManager,\n tableName: string,\n column: ColumnsWithAutoIncrement,\n position: number,\n total: number\n ): Promise<void> {\n const stat = await this.getMaxColumnIndex(\n em,\n tableName,\n column.column_name\n );\n const sequenceName = this.getSequenceName(column.column_default);\n if (!sequenceName) return;\n\n const index = Number(stat?.maxindex) || 0;\n this.updateTablesWithAutoIncrement(tableName, {\n column: column.column_name,\n sequenceName,\n index: String(index + (INDEX_OFFSET_CONFIG[this.getType()] ?? 0)),\n });\n this.logger.debug(\n \"🔁 Auto increment column processed\",\n `Table ${tableName}`,\n `Column ${column.column_name}`,\n `Sequence ${sequenceName}`,\n `Progress ${position}/${total}`\n );\n }\n\n private async getMaxColumnIndex(\n em: EntityManager,\n tableName: string,\n columnName: string\n ): Promise<ColumnStat | null> {\n const [stat] = await this.execQuery<ColumnStat>(em, \"getMaxColumnIndex\", {\n tableName,\n column_name: columnName,\n });\n return stat || null;\n }\n\n private getSequenceName(columnDefault: string): string | null {\n return columnDefault.match(/'([^']+)'/)?.[1] || null;\n }\n\n private updateTablesWithAutoIncrement(\n tableName: string,\n data: { column: string; sequenceName: string; index: string }\n ): void {\n if (!this.tablesWithAutoIncrement.has(tableName)) {\n this.tablesWithAutoIncrement.set(tableName, []);\n }\n\n this.tablesWithAutoIncrement.get(tableName)?.push(data);\n }\n\n public async restoreData(): Promise<void> {\n const tablesToRestore = this.getTablesForRestore();\n if (this.shouldTrackChanges() && this.changedTables.size === 0) {\n this.logger.debug(\n \"🕊️ No tracked table changes detected\",\n `Tables ${tablesToRestore.length}`\n );\n }\n const timer = this.logger.timer(\"Restore process\");\n const changeSummary = this.shouldTrackChanges()\n ? `Tracked changes ${this.changedTables.size}`\n : undefined;\n this.logger.verbose(\n \"🛠️ Restore process started\",\n `Tables selected ${tablesToRestore.length}`,\n changeSummary\n );\n await this.manager.transaction(async (em: EntityManager) => {\n const { foreignKey, restoreOrder } = await this.restoreManager(em);\n await foreignKey.disable();\n await restoreOrder();\n await foreignKey.enable();\n });\n timer.end(\n \"🎉 Restore process completed\",\n LogLevel.Info,\n `Tables restored ${tablesToRestore.length}`\n );\n }\n\n protected async restoreManager(em: EntityManager): Promise<Manager> {\n if (this.tables.size === 0) {\n await this.detectTables(em);\n }\n\n const manager: Manager = {\n foreignKey: {\n disable: async () => Promise.resolve(),\n enable: async () => Promise.resolve(),\n },\n restoreOrder: async () => Promise.resolve(),\n };\n\n const typesWithForeignKey: DBType[] = [\"postgres\", \"mariadb\", \"mysql\"];\n if (typesWithForeignKey.includes(this.getType())) {\n manager.foreignKey.disable = async (): Promise<void> => {\n this.logger.debug(\n \"🚧 Foreign keys disabled\",\n `Database ${this.getType()}`\n );\n await this.execQuery(em, \"foreignKey.disable\");\n };\n manager.foreignKey.enable = async (): Promise<void> => {\n await this.execQuery(em, \"foreignKey.enable\");\n this.logger.debug(\n \"🆗 Foreign keys enabled\",\n `Database ${this.getType()}`\n );\n };\n }\n\n manager.restoreOrder = (): Promise<void> => this.restoreOrder(em);\n\n return manager;\n }\n\n private async calculateDependencyTables(em: EntityManager): Promise<void> {\n const timer = this.logger.timer(\"Dependency planning\");\n this.logger.debug(\"🧭 Calculating dependency order for restore\");\n const dependencyTree = await this.execQuery<DependencyTreeQueryOut>(\n em,\n \"dependencyTree\"\n );\n\n if (!dependencyTree.length) {\n this.restoreInOder = false;\n timer.end(\n \"🧭 Dependency order calculated\",\n LogLevel.Debug,\n \"Mode parallel\",\n `Tables ${this.tables.size}`\n );\n return;\n }\n\n const sortedTables = new Set(dependencyTree.map((row) => row.table_name));\n this.tables.clear();\n this.tables = sortedTables;\n this.restoreInOder = true;\n timer.end(\n \"🧭 Dependency order calculated\",\n LogLevel.Debug,\n \"Mode ordered\",\n `Tables ${this.tables.size}`\n );\n }\n\n private async detectTables(em: EntityManager): Promise<void> {\n const timer = this.logger.timer(\"Table discovery\");\n this.logger.debug(\"🗂️ Discovering tables from database\");\n const tables = await this.execQuery<Table>(em, \"getTables\");\n if (!tables) {\n timer.end(\n \"🗂️ Table discovery completed\",\n LogLevel.Debug,\n `Tables ${this.tables.size}`\n );\n return;\n }\n\n tables.forEach((row) => {\n this.tables.add(row.name);\n });\n timer.end(\n \"🗂️ Table discovery completed\",\n LogLevel.Debug,\n `Tables ${this.tables.size}`\n );\n }\n\n private async restoreOrder(em: EntityManager): Promise<void> {\n const tables = this.getTablesForRestore();\n const totalTables = tables.length;\n if (this.restoreInOder) {\n this.logger.verbose(\"🧱 Restore mode ordered\", `Tables ${totalTables}`);\n for (const [index, tableName] of tables.entries()) {\n await this.recreateData(\n em,\n tableName,\n index + PROGRESS_OFFSET,\n totalTables\n );\n }\n } else {\n this.logger.verbose(\"🧱 Restore mode parallel\", `Tables ${totalTables}`);\n await Promise.all(\n tables.map((tableName, index) =>\n this.recreateData(\n em,\n tableName,\n index + PROGRESS_OFFSET,\n totalTables\n )\n )\n );\n }\n if (this.shouldTrackChanges()) {\n this.changedTables.clear();\n }\n }\n\n private async recreateData(\n em: EntityManager,\n tableName: string,\n position: number,\n total: number\n ): Promise<void> {\n const timer = this.logger.timer(`Restore ${tableName}`);\n this.logger.debug(\n \"📥 Restoring table\",\n `Table ${tableName}`,\n `Progress ${position}/${total}`\n );\n await this.execQuery(em, \"truncateTable\", { tableName });\n timer.mark(\n \"🧹 Table truncated\",\n LogLevel.Debug,\n `Table ${tableName}`,\n `Progress ${position}/${total}`\n );\n await this.execQuery(em, \"restoreData\", { tableName });\n timer.mark(\n \"📦 Table data restored\",\n LogLevel.Debug,\n `Table ${tableName}`,\n `Progress ${position}/${total}`\n );\n await this.resetAutoIncrementColumns(em, tableName);\n timer.end(\n \"✅ Table restored\",\n LogLevel.Info,\n `Table ${tableName}`,\n `Progress ${position}/${total}`\n );\n }\n\n private async resetAutoIncrementColumns(\n em: EntityManager,\n tableName: string\n ): Promise<void> {\n const tables = this.tablesWithAutoIncrement.get(tableName);\n if (!tables) return;\n\n for (const { column, sequenceName, index } of tables) {\n await this.execQuery(em, \"resetAutoIncrementColumn\", {\n tableName,\n column,\n sequenceName,\n index,\n });\n this.logger.debug(\n \"♻️ Auto increment column reset\",\n `Table ${tableName}`,\n `Column ${column}`,\n `Sequence ${sequenceName}`,\n `Next value ${index}`\n );\n }\n }\n\n private registerSubscriber(connection: DataSource | Connection): void {\n const subscriber = new ChangeTrackerSubscriber((tableName) => {\n this.markTableAsChanged(tableName);\n });\n this.getSubscriberCollection(connection).push(subscriber);\n this.bindSubscriber(subscriber, connection);\n this.logger.info(\n \"📡 Change tracking subscriber registered\",\n `Database ${this.getType()}`\n );\n }\n\n private isDataSource(\n connection: DataSource | Connection\n ): connection is DataSource {\n return connection instanceof DataSource;\n }\n\n private getSubscriberCollection(\n connection: DataSource | Connection\n ): Array<EntitySubscriberInterface<unknown>> {\n return (connection as unknown as {\n subscribers: Array<EntitySubscriberInterface<unknown>>;\n }).subscribers;\n }\n\n private bindSubscriber(\n subscriber: ChangeTrackerSubscriber,\n connection: DataSource | Connection\n ): void {\n const lifecycle = subscriber as ChangeTrackerSubscriber & SubscriberLifecycle;\n if (this.isDataSource(connection)) {\n lifecycle.setDataSource?.(connection);\n return;\n }\n lifecycle.setConnection?.(connection);\n }\n\n private shouldTrackChanges(): boolean {\n return (\n this.options.changeDetectionStrategy ===\n ChangeDetectionStrategy.Subscriber\n );\n }\n\n private getTablesForRestore(): string[] {\n const tables = [...this.tables];\n if (!this.shouldTrackChanges()) {\n return tables;\n }\n if (this.changedTables.size === 0) {\n return tables;\n }\n const changed = new Set(this.changedTables);\n const filtered = tables.filter((table) => changed.has(table));\n if (filtered.length === 0) {\n return tables;\n }\n this.logger.debug(\n \"🗜️ Filtering tables by tracked changes\",\n `Matched tables ${filtered.length}`,\n `Total tables ${tables.length}`\n );\n return filtered;\n }\n\n public markTableAsChanged(tableName: string): void {\n if (!this.shouldTrackChanges()) {\n return;\n }\n const wasTracked = this.changedTables.has(tableName);\n this.changedTables.add(tableName);\n if (!wasTracked) {\n this.logger.debug(\n \"🔎 Table change detected\",\n `Table ${tableName}`,\n `Tracked tables ${this.changedTables.size}`\n );\n }\n }\n\n private resolveLoggingConfiguration(\n logging?: boolean | LoggingOptions\n ): LoggingOptions | undefined {\n if (typeof logging === \"boolean\") {\n return { enabled: logging };\n }\n if (!logging) {\n return undefined;\n }\n if (logging.enabled === undefined) {\n return { ...logging, enabled: true };\n }\n return logging;\n }\n}\n\ntype SubscriberLifecycle = {\n setDataSource?: (dataSource: DataSource) => unknown;\n setConnection?: (connection: Connection) => unknown;\n};\n"],"names":["Fastypest","PROGRESS_OFFSET","SQLScript","init","timer","logger","verbose","getType","manager","transaction","em","detectTables","calculateDependencyTables","tables","Promise","all","createTempTable","detectTablesWithAutoIncrement","end","LogLevel","Info","size","tablesWithAutoIncrement","totalTables","length","map","tableName","index","execQuery","debug","entries","processTable","position","total","columns","getColumnsWithAutoIncrement","column","processColumn","Array","isArray","stat","getMaxColumnIndex","column_name","sequenceName","getSequenceName","column_default","Number","maxindex","updateTablesWithAutoIncrement","String","INDEX_OFFSET_CONFIG","columnName","columnDefault","match","data","has","set","get","push","restoreData","tablesToRestore","getTablesForRestore","shouldTrackChanges","changedTables","changeSummary","undefined","foreignKey","restoreOrder","restoreManager","disable","enable","resolve","typesWithForeignKey","includes","dependencyTree","restoreInOder","Debug","sortedTables","Set","row","table_name","clear","forEach","add","name","recreateData","mark","resetAutoIncrementColumns","registerSubscriber","connection","subscriber","ChangeTrackerSubscriber","markTableAsChanged","getSubscriberCollection","bindSubscriber","info","isDataSource","DataSource","subscribers","lifecycle","setDataSource","setConnection","options","changeDetectionStrategy","ChangeDetectionStrategy","Subscriber","changed","filtered","filter","table","wasTracked","resolveLoggingConfiguration","logging","enabled","type","Map","loggingConfiguration","resolvedLogging","configureLogging","createScopedLogger","None","detailLevels","detail","LOGGING_DETAIL_LEVELS","customLevels","levels","activeLevels","level","LOGGING_LEVEL_SEQUENCE","activeLevelLabels","LOGGING_LEVEL_LABELS","detailText","LoggingDetailLevel","Simple","customLevelText","join","activeLevelText","loggingDetails","entry","Boolean","log","warn"],"mappings":"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"}
|
package/dist/core/index.d.ts
CHANGED
package/dist/core/index.js
CHANGED
|
@@ -2,7 +2,26 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get ChangeDetectionStrategy () {
|
|
13
|
+
return _types.ChangeDetectionStrategy;
|
|
14
|
+
},
|
|
15
|
+
get LogLevel () {
|
|
16
|
+
return _logging.LogLevel;
|
|
17
|
+
},
|
|
18
|
+
get LoggingDetailLevel () {
|
|
19
|
+
return _logging.LoggingDetailLevel;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
5
22
|
_export_star(require("./fastypest"), exports);
|
|
23
|
+
const _types = require("./types");
|
|
24
|
+
const _logging = require("../logging");
|
|
6
25
|
function _export_star(from, to) {
|
|
7
26
|
Object.keys(from).forEach(function(k) {
|
|
8
27
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/index.ts"],"sourcesContent":["export * from \"./fastypest\";\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/core/index.ts"],"sourcesContent":["export * from \"./fastypest\";\nexport { ChangeDetectionStrategy } from \"./types\";\nexport type { FastypestOptions } from \"./types\";\nexport { LogLevel, LoggingDetailLevel } from \"../logging\";\nexport type { LoggingOptions } from \"../logging\";\n"],"names":["ChangeDetectionStrategy","LogLevel","LoggingDetailLevel"],"mappings":";;;;;;;;;;;QACSA;eAAAA,8BAAuB;;QAEvBC;eAAAA,iBAAQ;;QAAEC;eAAAA,2BAAkB;;;qBAHvB;uBAC0B;yBAEK"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"getTables": "SELECT table_name AS name FROM information_schema.tables WHERE table_catalog = CURRENT_DATABASE() AND table_schema = 'public' AND table_type = 'BASE TABLE'",
|
|
8
8
|
"createTempTable": "SET experimental_enable_temp_tables=on; CREATE TEMPORARY TABLE \"{{tableName}}_temp\" AS SELECT * FROM \"{{tableName}}\"",
|
|
9
|
-
"dropTempTable": "DROP TABLE IF EXISTS \"{{tableName}}_temp\"",
|
|
9
|
+
"dropTempTable": "DROP TABLE IF EXISTS \"{{tableName}}_temp\";",
|
|
10
10
|
"restoreData": "INSERT INTO \"{{tableName}}\" SELECT * FROM \"{{tableName}}_temp\";",
|
|
11
11
|
"truncateTable": "TRUNCATE TABLE \"{{tableName}}\" CASCADE;",
|
|
12
12
|
"getColumnsWithAutoIncrement": "SELECT column_name, column_default FROM information_schema.columns WHERE table_schema = 'public' AND column_default LIKE 'nextval%' AND table_name = '{{tableName}}'",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"getTables": "SELECT table_name AS name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'",
|
|
8
8
|
"createTempTable": "CREATE TEMPORARY TABLE {{tableName}}_temp AS SELECT * FROM {{tableName}}",
|
|
9
|
-
"dropTempTable": "DROP TEMPORARY TABLE {{tableName}}_temp",
|
|
9
|
+
"dropTempTable": "DROP TEMPORARY TABLE IF EXISTS {{tableName}}_temp",
|
|
10
10
|
"restoreData": "INSERT INTO {{tableName}} SELECT * FROM {{tableName}}_temp",
|
|
11
11
|
"truncateTable": "TRUNCATE TABLE {{tableName}}",
|
|
12
12
|
"getColumnsWithAutoIncrement": "-- NOT USED",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"getTables": "SELECT table_name AS name FROM information_schema.tables WHERE table_schema = CURRENT_SCHEMA() AND table_type = 'BASE TABLE'",
|
|
8
8
|
"createTempTable": "CREATE TEMPORARY TABLE \"{{tableName}}_temp\" AS SELECT * FROM \"{{tableName}}\"",
|
|
9
|
-
"dropTempTable": "DROP TABLE IF EXISTS \"{{tableName}}_temp\"",
|
|
9
|
+
"dropTempTable": "DROP TABLE IF EXISTS \"{{tableName}}_temp\";",
|
|
10
10
|
"restoreData": "INSERT INTO \"{{tableName}}\" SELECT * FROM \"{{tableName}}_temp\";",
|
|
11
11
|
"truncateTable": "TRUNCATE TABLE \"{{tableName}}\" RESTART IDENTITY CASCADE",
|
|
12
12
|
"getColumnsWithAutoIncrement": "SELECT column_name, column_default FROM information_schema.columns WHERE table_schema = 'public' AND column_default LIKE 'nextval%' AND table_name = '{{tableName}}'",
|
|
@@ -5,6 +5,7 @@ type DBTypes = DataSourceOptions["type"];
|
|
|
5
5
|
export declare class SQLScript {
|
|
6
6
|
private readonly type;
|
|
7
7
|
private queries;
|
|
8
|
+
private readonly scriptLogger;
|
|
8
9
|
protected constructor(type: DBTypes);
|
|
9
10
|
protected getType(): DBTypes;
|
|
10
11
|
protected execQuery<T = void>(em: EntityManager, queryPath: QueryPath<Queries>, values?: Record<string, string>): T extends void ? Promise<void> : Promise<T[]>;
|
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "SQLScript", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _queries = require("./queries");
|
|
12
|
+
const _logging = require("../../logging");
|
|
12
13
|
function _define_property(obj, key, value) {
|
|
13
14
|
if (key in obj) {
|
|
14
15
|
Object.defineProperty(obj, key, {
|
|
@@ -34,12 +35,16 @@ class SQLScript {
|
|
|
34
35
|
query = query.replace(new RegExp(`{{\\s*${key}\\s*}}`, "g"), values[key]);
|
|
35
36
|
}
|
|
36
37
|
}
|
|
38
|
+
const parameterEntries = values ? Object.entries(values).map(([key, value])=>`${key}=${value}`) : [];
|
|
39
|
+
this.scriptLogger.debug("Executing SQL query", `Path ${queryPath}`, parameterEntries.length > 0 ? `Parameters ${parameterEntries.join(", ")}` : undefined);
|
|
37
40
|
return em.query(query);
|
|
38
41
|
}
|
|
39
42
|
constructor(type){
|
|
40
43
|
_define_property(this, "type", void 0);
|
|
41
44
|
_define_property(this, "queries", void 0);
|
|
45
|
+
_define_property(this, "scriptLogger", void 0);
|
|
42
46
|
this.type = type;
|
|
47
|
+
this.scriptLogger = (0, _logging.createScopedLogger)("SQLScript");
|
|
43
48
|
if (!(this.type in _queries.DB_QUERIES)) {
|
|
44
49
|
throw new Error(`The database type provided is not supported. Please choose from the following: ${Object.keys(_queries.DB_QUERIES)}`);
|
|
45
50
|
}
|