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 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:
@@ -1,12 +1,15 @@
1
1
  import { Connection, DataSource, EntityManager } from "typeorm";
2
2
  import { SQLScript } from "./sql-script";
3
- import type { Manager } from "./types";
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
- constructor(connection: DataSource | Connection);
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
  }
@@ -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
- await Promise.all(tables.map(async (tableName)=>{
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
- for (const tableName of tables){
49
- await this.processTable(em, tableName);
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 ()=>this.execQuery(em, "foreignKey.disable");
118
- manager.foreignKey.enable = async ()=>this.execQuery(em, "foreignKey.enable");
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) return;
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
- for (const tableName of this.tables){
144
- await this.recreateData(em, tableName);
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
- return;
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
- constructor(connection){
175
- 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);
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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"}
@@ -1 +1,5 @@
1
1
  export * from "./fastypest";
2
+ export { ChangeDetectionStrategy } from "./types";
3
+ export type { FastypestOptions } from "./types";
4
+ export { LogLevel, LoggingDetailLevel } from "../logging";
5
+ export type { LoggingOptions } from "../logging";
@@ -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)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/index.ts"],"sourcesContent":["export * from \"./fastypest\";\n"],"names":[],"mappings":";;;;qBAAc"}
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
  }