fastypest 1.5.1 → 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
@@ -68,6 +68,28 @@ const fastypest = new Fastypest(connection, {
68
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
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
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
+
71
93
  ## ⚙️ Flujo de trabajo automatizado
72
94
 
73
95
  Este proyecto usa un sistema CI/CD avanzado con GitHub Actions:
package/README.md CHANGED
@@ -69,6 +69,28 @@ const fastypest = new Fastypest(connection, {
69
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
70
  - TypeORM subscribers are not triggered by raw queries, so enabling the subscriber strategy requires using repositories or query builders for automatic tracking.
71
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
+
72
94
  ## ⚙️ Automated Workflow
73
95
 
74
96
  This project leverages a sophisticated CI/CD setup using GitHub Actions:
@@ -8,6 +8,7 @@ export declare class Fastypest extends SQLScript {
8
8
  private restoreInOder;
9
9
  private readonly options;
10
10
  private readonly changedTables;
11
+ private readonly logger;
11
12
  constructor(connection: DataSource | Connection, options?: FastypestOptions);
12
13
  init(): Promise<void>;
13
14
  private createTempTable;
@@ -32,4 +33,5 @@ export declare class Fastypest extends SQLScript {
32
33
  private shouldTrackChanges;
33
34
  private getTablesForRestore;
34
35
  markTableAsChanged(tableName: string): void;
36
+ private resolveLoggingConfiguration;
35
37
  }
@@ -13,6 +13,7 @@ const _config = require("./config");
13
13
  const _sqlscript = require("./sql-script");
14
14
  const _changetrackersubscriber = require("./subscribers/change-tracker.subscriber");
15
15
  const _types = require("./types");
16
+ const _logging = require("../logging");
16
17
  function _define_property(obj, key, value) {
17
18
  if (key in obj) {
18
19
  Object.defineProperty(obj, key, {
@@ -26,8 +27,11 @@ function _define_property(obj, key, value) {
26
27
  }
27
28
  return obj;
28
29
  }
30
+ const PROGRESS_OFFSET = 1;
29
31
  class Fastypest extends _sqlscript.SQLScript {
30
32
  async init() {
33
+ const timer = this.logger.timer("Initialization");
34
+ this.logger.verbose("🚀 Initialization started", `Database ${this.getType()}`);
31
35
  await this.manager.transaction(async (em)=>{
32
36
  await this.detectTables(em);
33
37
  await this.calculateDependencyTables(em);
@@ -39,27 +43,32 @@ class Fastypest extends _sqlscript.SQLScript {
39
43
  this.detectTablesWithAutoIncrement(em, tables)
40
44
  ]);
41
45
  });
46
+ timer.end("✅ Initialization completed", _logging.LogLevel.Info, `Tables ${this.tables.size}`, `Tables with auto increment ${this.tablesWithAutoIncrement.size}`);
42
47
  }
43
48
  async createTempTable(em, tables) {
44
- await Promise.all(tables.map(async (tableName)=>{
49
+ const totalTables = tables.length;
50
+ await Promise.all(tables.map(async (tableName, index)=>{
45
51
  await this.execQuery(em, "dropTempTable", {
46
52
  tableName
47
53
  });
48
54
  await this.execQuery(em, "createTempTable", {
49
55
  tableName
50
56
  });
57
+ this.logger.debug("🧪 Temporary table prepared", `Table ${tableName}`, `Progress ${index + PROGRESS_OFFSET}/${totalTables}`);
51
58
  }));
52
59
  }
53
60
  async detectTablesWithAutoIncrement(em, tables) {
54
- for (const tableName of tables){
55
- 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);
56
64
  }
65
+ this.logger.debug("📊 Auto increment analysis completed", `Tables with auto increment ${this.tablesWithAutoIncrement.size}`);
57
66
  }
58
- async processTable(em, tableName) {
67
+ async processTable(em, tableName, position, total) {
59
68
  const columns = await this.getColumnsWithAutoIncrement(em, tableName);
60
69
  if (!columns) return;
61
70
  for (const column of columns){
62
- await this.processColumn(em, tableName, column);
71
+ await this.processColumn(em, tableName, column, position, total);
63
72
  }
64
73
  }
65
74
  async getColumnsWithAutoIncrement(em, tableName) {
@@ -68,7 +77,7 @@ class Fastypest extends _sqlscript.SQLScript {
68
77
  });
69
78
  return Array.isArray(columns) ? columns : null;
70
79
  }
71
- async processColumn(em, tableName, column) {
80
+ async processColumn(em, tableName, column, position, total) {
72
81
  const stat = await this.getMaxColumnIndex(em, tableName, column.column_name);
73
82
  const sequenceName = this.getSequenceName(column.column_default);
74
83
  if (!sequenceName) return;
@@ -78,6 +87,7 @@ class Fastypest extends _sqlscript.SQLScript {
78
87
  sequenceName,
79
88
  index: String(index + (_config.INDEX_OFFSET_CONFIG[this.getType()] ?? 0))
80
89
  });
90
+ this.logger.debug("🔁 Auto increment column processed", `Table ${tableName}`, `Column ${column.column_name}`, `Sequence ${sequenceName}`, `Progress ${position}/${total}`);
81
91
  }
82
92
  async getMaxColumnIndex(em, tableName, columnName) {
83
93
  const [stat] = await this.execQuery(em, "getMaxColumnIndex", {
@@ -96,12 +106,20 @@ class Fastypest extends _sqlscript.SQLScript {
96
106
  this.tablesWithAutoIncrement.get(tableName)?.push(data);
97
107
  }
98
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);
99
116
  await this.manager.transaction(async (em)=>{
100
117
  const { foreignKey, restoreOrder } = await this.restoreManager(em);
101
118
  await foreignKey.disable();
102
119
  await restoreOrder();
103
120
  await foreignKey.enable();
104
121
  });
122
+ timer.end("🎉 Restore process completed", _logging.LogLevel.Info, `Tables restored ${tablesToRestore.length}`);
105
123
  }
106
124
  async restoreManager(em) {
107
125
  if (this.tables.size === 0) {
@@ -120,51 +138,75 @@ class Fastypest extends _sqlscript.SQLScript {
120
138
  "mysql"
121
139
  ];
122
140
  if (typesWithForeignKey.includes(this.getType())) {
123
- manager.foreignKey.disable = async ()=>this.execQuery(em, "foreignKey.disable");
124
- 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
+ };
125
149
  }
126
150
  manager.restoreOrder = ()=>this.restoreOrder(em);
127
151
  return manager;
128
152
  }
129
153
  async calculateDependencyTables(em) {
154
+ const timer = this.logger.timer("Dependency planning");
155
+ this.logger.debug("🧭 Calculating dependency order for restore");
130
156
  const dependencyTree = await this.execQuery(em, "dependencyTree");
131
157
  if (!dependencyTree.length) {
132
158
  this.restoreInOder = false;
159
+ timer.end("🧭 Dependency order calculated", _logging.LogLevel.Debug, "Mode parallel", `Tables ${this.tables.size}`);
133
160
  return;
134
161
  }
135
162
  const sortedTables = new Set(dependencyTree.map((row)=>row.table_name));
136
163
  this.tables.clear();
137
164
  this.tables = sortedTables;
138
165
  this.restoreInOder = true;
166
+ timer.end("🧭 Dependency order calculated", _logging.LogLevel.Debug, "Mode ordered", `Tables ${this.tables.size}`);
139
167
  }
140
168
  async detectTables(em) {
169
+ const timer = this.logger.timer("Table discovery");
170
+ this.logger.debug("🗂️ Discovering tables from database");
141
171
  const tables = await this.execQuery(em, "getTables");
142
- if (!tables) return;
172
+ if (!tables) {
173
+ timer.end("🗂️ Table discovery completed", _logging.LogLevel.Debug, `Tables ${this.tables.size}`);
174
+ return;
175
+ }
143
176
  tables.forEach((row)=>{
144
177
  this.tables.add(row.name);
145
178
  });
179
+ timer.end("🗂️ Table discovery completed", _logging.LogLevel.Debug, `Tables ${this.tables.size}`);
146
180
  }
147
181
  async restoreOrder(em) {
148
182
  const tables = this.getTablesForRestore();
183
+ const totalTables = tables.length;
149
184
  if (this.restoreInOder) {
150
- for (const tableName of tables){
151
- 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);
152
188
  }
153
189
  } else {
154
- await Promise.all(tables.map((tableName)=>this.recreateData(em, tableName)));
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)));
155
192
  }
156
193
  if (this.shouldTrackChanges()) {
157
194
  this.changedTables.clear();
158
195
  }
159
196
  }
160
- 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}`);
161
200
  await this.execQuery(em, "truncateTable", {
162
201
  tableName
163
202
  });
203
+ timer.mark("🧹 Table truncated", _logging.LogLevel.Debug, `Table ${tableName}`, `Progress ${position}/${total}`);
164
204
  await this.execQuery(em, "restoreData", {
165
205
  tableName
166
206
  });
207
+ timer.mark("📦 Table data restored", _logging.LogLevel.Debug, `Table ${tableName}`, `Progress ${position}/${total}`);
167
208
  await this.resetAutoIncrementColumns(em, tableName);
209
+ timer.end("✅ Table restored", _logging.LogLevel.Info, `Table ${tableName}`, `Progress ${position}/${total}`);
168
210
  }
169
211
  async resetAutoIncrementColumns(em, tableName) {
170
212
  const tables = this.tablesWithAutoIncrement.get(tableName);
@@ -176,6 +218,7 @@ class Fastypest extends _sqlscript.SQLScript {
176
218
  sequenceName,
177
219
  index
178
220
  });
221
+ this.logger.debug("♻️ Auto increment column reset", `Table ${tableName}`, `Column ${column}`, `Sequence ${sequenceName}`, `Next value ${index}`);
179
222
  }
180
223
  }
181
224
  registerSubscriber(connection) {
@@ -184,6 +227,7 @@ class Fastypest extends _sqlscript.SQLScript {
184
227
  });
185
228
  this.getSubscriberCollection(connection).push(subscriber);
186
229
  this.bindSubscriber(subscriber, connection);
230
+ this.logger.info("📡 Change tracking subscriber registered", `Database ${this.getType()}`);
187
231
  }
188
232
  isDataSource(connection) {
189
233
  return connection instanceof _typeorm.DataSource;
@@ -217,21 +261,66 @@ class Fastypest extends _sqlscript.SQLScript {
217
261
  if (filtered.length === 0) {
218
262
  return tables;
219
263
  }
264
+ this.logger.debug("🗜️ Filtering tables by tracked changes", `Matched tables ${filtered.length}`, `Total tables ${tables.length}`);
220
265
  return filtered;
221
266
  }
222
267
  markTableAsChanged(tableName) {
223
268
  if (!this.shouldTrackChanges()) {
224
269
  return;
225
270
  }
271
+ const wasTracked = this.changedTables.has(tableName);
226
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;
227
293
  }
228
294
  constructor(connection, options){
229
- 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());
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");
230
299
  this.manager = connection.manager;
231
300
  this.options = {
232
301
  changeDetectionStrategy: options?.changeDetectionStrategy ?? _types.ChangeDetectionStrategy.None
233
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
+ }
234
322
  if (this.options.changeDetectionStrategy === _types.ChangeDetectionStrategy.Subscriber) {
323
+ this.logger.info("🛰️ Change detection strategy enabled");
235
324
  this.registerSubscriber(connection);
236
325
  }
237
326
  }
@@ -1 +1 @@
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\";\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<FastypestOptions>;\n private readonly changedTables: Set<string> = new Set();\n\n constructor(\n connection: DataSource | Connection,\n options?: FastypestOptions\n ) {\n super(connection.options.type);\n this.manager = connection.manager;\n this.options = {\n changeDetectionStrategy:\n options?.changeDetectionStrategy ?? ChangeDetectionStrategy.None,\n };\n if (\n this.options.changeDetectionStrategy ===\n ChangeDetectionStrategy.Subscriber\n ) {\n this.registerSubscriber(connection);\n }\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, \"dropTempTable\", { 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 const tables = this.getTablesForRestore();\n if (this.restoreInOder) {\n for (const tableName of tables) {\n await this.recreateData(em, tableName);\n }\n } else {\n await Promise.all(\n tables.map((tableName) => this.recreateData(em, tableName))\n );\n }\n if (this.shouldTrackChanges()) {\n this.changedTables.clear();\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 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 }\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 return filtered;\n }\n\n public markTableAsChanged(tableName: string): void {\n if (!this.shouldTrackChanges()) {\n return;\n }\n this.changedTables.add(tableName);\n }\n}\n\ntype SubscriberLifecycle = {\n setDataSource?: (dataSource: DataSource) => unknown;\n setConnection?: (connection: Connection) => unknown;\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","getTablesForRestore","recreateData","shouldTrackChanges","changedTables","resetAutoIncrementColumns","registerSubscriber","connection","subscriber","ChangeTrackerSubscriber","markTableAsChanged","getSubscriberCollection","bindSubscriber","isDataSource","DataSource","subscribers","lifecycle","setDataSource","setConnection","options","changeDetectionStrategy","ChangeDetectionStrategy","Subscriber","changed","filtered","filter","table","type","Map","None"],"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":";;;;+BAiCaA;;;eAAAA;;;yBA3BN;wBAC6B;2BACV;yCACc;uBAUjC;yBASA;;;;;;;;;;;;;;AAGP,MAAMC,kBAAkB;AAEjB,MAAMD,kBAAkBE,oBAAS;IA0EtC,MAAaC,OAAsB;QACjC,MAAMC,QAAQ,IAAI,CAACC,MAAM,CAACD,KAAK,CAAC;QAChC,IAAI,CAACC,MAAM,CAACC,OAAO,CAAC,6BAA6B,CAAC,SAAS,EAAE,IAAI,CAACC,OAAO,IAAI;QAC7E,MAAM,IAAI,CAACC,OAAO,CAACC,WAAW,CAAC,OAAOC;YACpC,MAAM,IAAI,CAACC,YAAY,CAACD;YACxB,MAAM,IAAI,CAACE,yBAAyB,CAACF;YACrC,MAAMG,SAAS;mBAAI,IAAI,CAACA,MAAM;aAAC;YAC/B,MAAMC,QAAQC,GAAG,CAAC;gBAChB,IAAI,CAACC,eAAe,CAACN,IAAIG;gBACzB,IAAI,CAACI,6BAA6B,CAACP,IAAIG;aACxC;QACH;QACAT,MAAMc,GAAG,CACP,8BACAC,iBAAQ,CAACC,IAAI,EACb,CAAC,OAAO,EAAE,IAAI,CAACP,MAAM,CAACQ,IAAI,EAAE,EAC5B,CAAC,2BAA2B,EAAE,IAAI,CAACC,uBAAuB,CAACD,IAAI,EAAE;IAErE;IAEA,MAAcL,gBACZN,EAAiB,EACjBG,MAAgB,EACD;QACf,MAAMU,cAAcV,OAAOW,MAAM;QACjC,MAAMV,QAAQC,GAAG,CACfF,OAAOY,GAAG,CAAC,OAAOC,WAAWC;YAC3B,MAAM,IAAI,CAACC,SAAS,CAAClB,IAAI,iBAAiB;gBAAEgB;YAAU;YACtD,MAAM,IAAI,CAACE,SAAS,CAAClB,IAAI,mBAAmB;gBAAEgB;YAAU;YACxD,IAAI,CAACrB,MAAM,CAACwB,KAAK,CACf,+BACA,CAAC,MAAM,EAAEH,WAAW,EACpB,CAAC,SAAS,EAAEC,QAAQ1B,gBAAgB,CAAC,EAAEsB,aAAa;QAExD;IAEJ;IAEA,MAAcN,8BACZP,EAAiB,EACjBG,MAAgB,EACD;QACf,MAAMU,cAAcV,OAAOW,MAAM;QACjC,KAAK,MAAM,CAACG,OAAOD,UAAU,IAAIb,OAAOiB,OAAO,GAAI;YACjD,MAAM,IAAI,CAACC,YAAY,CAACrB,IAAIgB,WAAWC,QAAQ1B,iBAAiBsB;QAClE;QACA,IAAI,CAAClB,MAAM,CAACwB,KAAK,CACf,wCACA,CAAC,2BAA2B,EAAE,IAAI,CAACP,uBAAuB,CAACD,IAAI,EAAE;IAErE;IAEA,MAAcU,aACZrB,EAAiB,EACjBgB,SAAiB,EACjBM,QAAgB,EAChBC,KAAa,EACE;QACf,MAAMC,UAAU,MAAM,IAAI,CAACC,2BAA2B,CAACzB,IAAIgB;QAC3D,IAAI,CAACQ,SAAS;QAEd,KAAK,MAAME,UAAUF,QAAS;YAC5B,MAAM,IAAI,CAACG,aAAa,CAAC3B,IAAIgB,WAAWU,QAAQJ,UAAUC;QAC5D;IACF;IAEA,MAAcE,4BACZzB,EAAiB,EACjBgB,SAAiB,EAC2B;QAC5C,MAAMQ,UAAU,MAAM,IAAI,CAACN,SAAS,CAClClB,IACA,+BACA;YAAEgB;QAAU;QAEd,OAAOY,MAAMC,OAAO,CAACL,WAAWA,UAAU;IAC5C;IAEA,MAAcG,cACZ3B,EAAiB,EACjBgB,SAAiB,EACjBU,MAAgC,EAChCJ,QAAgB,EAChBC,KAAa,EACE;QACf,MAAMO,OAAO,MAAM,IAAI,CAACC,iBAAiB,CACvC/B,IACAgB,WACAU,OAAOM,WAAW;QAEpB,MAAMC,eAAe,IAAI,CAACC,eAAe,CAACR,OAAOS,cAAc;QAC/D,IAAI,CAACF,cAAc;QAEnB,MAAMhB,QAAQmB,OAAON,MAAMO,aAAa;QACxC,IAAI,CAACC,6BAA6B,CAACtB,WAAW;YAC5CU,QAAQA,OAAOM,WAAW;YAC1BC;YACAhB,OAAOsB,OAAOtB,QAASuB,CAAAA,2BAAmB,CAAC,IAAI,CAAC3C,OAAO,GAAG,IAAI,CAAA;QAChE;QACA,IAAI,CAACF,MAAM,CAACwB,KAAK,CACf,sCACA,CAAC,MAAM,EAAEH,WAAW,EACpB,CAAC,OAAO,EAAEU,OAAOM,WAAW,EAAE,EAC9B,CAAC,SAAS,EAAEC,cAAc,EAC1B,CAAC,SAAS,EAAEX,SAAS,CAAC,EAAEC,OAAO;IAEnC;IAEA,MAAcQ,kBACZ/B,EAAiB,EACjBgB,SAAiB,EACjByB,UAAkB,EACU;QAC5B,MAAM,CAACX,KAAK,GAAG,MAAM,IAAI,CAACZ,SAAS,CAAalB,IAAI,qBAAqB;YACvEgB;YACAgB,aAAaS;QACf;QACA,OAAOX,QAAQ;IACjB;IAEQI,gBAAgBQ,aAAqB,EAAiB;QAC5D,OAAOA,cAAcC,KAAK,CAAC,cAAc,CAAC,EAAE,IAAI;IAClD;IAEQL,8BACNtB,SAAiB,EACjB4B,IAA6D,EACvD;QACN,IAAI,CAAC,IAAI,CAAChC,uBAAuB,CAACiC,GAAG,CAAC7B,YAAY;YAChD,IAAI,CAACJ,uBAAuB,CAACkC,GAAG,CAAC9B,WAAW,EAAE;QAChD;QAEA,IAAI,CAACJ,uBAAuB,CAACmC,GAAG,CAAC/B,YAAYgC,KAAKJ;IACpD;IAEA,MAAaK,cAA6B;QACxC,MAAMC,kBAAkB,IAAI,CAACC,mBAAmB;QAChD,IAAI,IAAI,CAACC,kBAAkB,MAAM,IAAI,CAACC,aAAa,CAAC1C,IAAI,KAAK,GAAG;YAC9D,IAAI,CAAChB,MAAM,CAACwB,KAAK,CACf,yCACA,CAAC,OAAO,EAAE+B,gBAAgBpC,MAAM,EAAE;QAEtC;QACA,MAAMpB,QAAQ,IAAI,CAACC,MAAM,CAACD,KAAK,CAAC;QAChC,MAAM4D,gBAAgB,IAAI,CAACF,kBAAkB,KACzC,CAAC,gBAAgB,EAAE,IAAI,CAACC,aAAa,CAAC1C,IAAI,EAAE,GAC5C4C;QACJ,IAAI,CAAC5D,MAAM,CAACC,OAAO,CACjB,+BACA,CAAC,gBAAgB,EAAEsD,gBAAgBpC,MAAM,EAAE,EAC3CwC;QAEF,MAAM,IAAI,CAACxD,OAAO,CAACC,WAAW,CAAC,OAAOC;YACpC,MAAM,EAAEwD,UAAU,EAAEC,YAAY,EAAE,GAAG,MAAM,IAAI,CAACC,cAAc,CAAC1D;YAC/D,MAAMwD,WAAWG,OAAO;YACxB,MAAMF;YACN,MAAMD,WAAWI,MAAM;QACzB;QACAlE,MAAMc,GAAG,CACP,gCACAC,iBAAQ,CAACC,IAAI,EACb,CAAC,gBAAgB,EAAEwC,gBAAgBpC,MAAM,EAAE;IAE/C;IAEA,MAAgB4C,eAAe1D,EAAiB,EAAoB;QAClE,IAAI,IAAI,CAACG,MAAM,CAACQ,IAAI,KAAK,GAAG;YAC1B,MAAM,IAAI,CAACV,YAAY,CAACD;QAC1B;QAEA,MAAMF,UAAmB;YACvB0D,YAAY;gBACVG,SAAS,UAAYvD,QAAQyD,OAAO;gBACpCD,QAAQ,UAAYxD,QAAQyD,OAAO;YACrC;YACAJ,cAAc,UAAYrD,QAAQyD,OAAO;QAC3C;QAEA,MAAMC,sBAAgC;YAAC;YAAY;YAAW;SAAQ;QACtE,IAAIA,oBAAoBC,QAAQ,CAAC,IAAI,CAAClE,OAAO,KAAK;YAChDC,QAAQ0D,UAAU,CAACG,OAAO,GAAG;gBAC3B,IAAI,CAAChE,MAAM,CAACwB,KAAK,CACf,4BACA,CAAC,SAAS,EAAE,IAAI,CAACtB,OAAO,IAAI;gBAE9B,MAAM,IAAI,CAACqB,SAAS,CAAClB,IAAI;YAC3B;YACAF,QAAQ0D,UAAU,CAACI,MAAM,GAAG;gBAC1B,MAAM,IAAI,CAAC1C,SAAS,CAAClB,IAAI;gBACzB,IAAI,CAACL,MAAM,CAACwB,KAAK,CACf,2BACA,CAAC,SAAS,EAAE,IAAI,CAACtB,OAAO,IAAI;YAEhC;QACF;QAEAC,QAAQ2D,YAAY,GAAG,IAAqB,IAAI,CAACA,YAAY,CAACzD;QAE9D,OAAOF;IACT;IAEA,MAAcI,0BAA0BF,EAAiB,EAAiB;QACxE,MAAMN,QAAQ,IAAI,CAACC,MAAM,CAACD,KAAK,CAAC;QAChC,IAAI,CAACC,MAAM,CAACwB,KAAK,CAAC;QAClB,MAAM6C,iBAAiB,MAAM,IAAI,CAAC9C,SAAS,CACzClB,IACA;QAGF,IAAI,CAACgE,eAAelD,MAAM,EAAE;YAC1B,IAAI,CAACmD,aAAa,GAAG;YACrBvE,MAAMc,GAAG,CACP,kCACAC,iBAAQ,CAACyD,KAAK,EACd,iBACA,CAAC,OAAO,EAAE,IAAI,CAAC/D,MAAM,CAACQ,IAAI,EAAE;YAE9B;QACF;QAEA,MAAMwD,eAAe,IAAIC,IAAIJ,eAAejD,GAAG,CAAC,CAACsD,MAAQA,IAAIC,UAAU;QACvE,IAAI,CAACnE,MAAM,CAACoE,KAAK;QACjB,IAAI,CAACpE,MAAM,GAAGgE;QACd,IAAI,CAACF,aAAa,GAAG;QACrBvE,MAAMc,GAAG,CACP,kCACAC,iBAAQ,CAACyD,KAAK,EACd,gBACA,CAAC,OAAO,EAAE,IAAI,CAAC/D,MAAM,CAACQ,IAAI,EAAE;IAEhC;IAEA,MAAcV,aAAaD,EAAiB,EAAiB;QAC3D,MAAMN,QAAQ,IAAI,CAACC,MAAM,CAACD,KAAK,CAAC;QAChC,IAAI,CAACC,MAAM,CAACwB,KAAK,CAAC;QAClB,MAAMhB,SAAS,MAAM,IAAI,CAACe,SAAS,CAAQlB,IAAI;QAC/C,IAAI,CAACG,QAAQ;YACXT,MAAMc,GAAG,CACP,iCACAC,iBAAQ,CAACyD,KAAK,EACd,CAAC,OAAO,EAAE,IAAI,CAAC/D,MAAM,CAACQ,IAAI,EAAE;YAE9B;QACF;QAEAR,OAAOqE,OAAO,CAAC,CAACH;YACd,IAAI,CAAClE,MAAM,CAACsE,GAAG,CAACJ,IAAIK,IAAI;QAC1B;QACAhF,MAAMc,GAAG,CACP,iCACAC,iBAAQ,CAACyD,KAAK,EACd,CAAC,OAAO,EAAE,IAAI,CAAC/D,MAAM,CAACQ,IAAI,EAAE;IAEhC;IAEA,MAAc8C,aAAazD,EAAiB,EAAiB;QAC3D,MAAMG,SAAS,IAAI,CAACgD,mBAAmB;QACvC,MAAMtC,cAAcV,OAAOW,MAAM;QACjC,IAAI,IAAI,CAACmD,aAAa,EAAE;YACtB,IAAI,CAACtE,MAAM,CAACC,OAAO,CAAC,2BAA2B,CAAC,OAAO,EAAEiB,aAAa;YACtE,KAAK,MAAM,CAACI,OAAOD,UAAU,IAAIb,OAAOiB,OAAO,GAAI;gBACjD,MAAM,IAAI,CAACuD,YAAY,CACrB3E,IACAgB,WACAC,QAAQ1B,iBACRsB;YAEJ;QACF,OAAO;YACL,IAAI,CAAClB,MAAM,CAACC,OAAO,CAAC,4BAA4B,CAAC,OAAO,EAAEiB,aAAa;YACvE,MAAMT,QAAQC,GAAG,CACfF,OAAOY,GAAG,CAAC,CAACC,WAAWC,QACrB,IAAI,CAAC0D,YAAY,CACf3E,IACAgB,WACAC,QAAQ1B,iBACRsB;QAIR;QACA,IAAI,IAAI,CAACuC,kBAAkB,IAAI;YAC7B,IAAI,CAACC,aAAa,CAACkB,KAAK;QAC1B;IACF;IAEA,MAAcI,aACZ3E,EAAiB,EACjBgB,SAAiB,EACjBM,QAAgB,EAChBC,KAAa,EACE;QACf,MAAM7B,QAAQ,IAAI,CAACC,MAAM,CAACD,KAAK,CAAC,CAAC,QAAQ,EAAEsB,WAAW;QACtD,IAAI,CAACrB,MAAM,CAACwB,KAAK,CACf,sBACA,CAAC,MAAM,EAAEH,WAAW,EACpB,CAAC,SAAS,EAAEM,SAAS,CAAC,EAAEC,OAAO;QAEjC,MAAM,IAAI,CAACL,SAAS,CAAClB,IAAI,iBAAiB;YAAEgB;QAAU;QACtDtB,MAAMkF,IAAI,CACR,sBACAnE,iBAAQ,CAACyD,KAAK,EACd,CAAC,MAAM,EAAElD,WAAW,EACpB,CAAC,SAAS,EAAEM,SAAS,CAAC,EAAEC,OAAO;QAEjC,MAAM,IAAI,CAACL,SAAS,CAAClB,IAAI,eAAe;YAAEgB;QAAU;QACpDtB,MAAMkF,IAAI,CACR,0BACAnE,iBAAQ,CAACyD,KAAK,EACd,CAAC,MAAM,EAAElD,WAAW,EACpB,CAAC,SAAS,EAAEM,SAAS,CAAC,EAAEC,OAAO;QAEjC,MAAM,IAAI,CAACsD,yBAAyB,CAAC7E,IAAIgB;QACzCtB,MAAMc,GAAG,CACP,oBACAC,iBAAQ,CAACC,IAAI,EACb,CAAC,MAAM,EAAEM,WAAW,EACpB,CAAC,SAAS,EAAEM,SAAS,CAAC,EAAEC,OAAO;IAEnC;IAEA,MAAcsD,0BACZ7E,EAAiB,EACjBgB,SAAiB,EACF;QACf,MAAMb,SAAS,IAAI,CAACS,uBAAuB,CAACmC,GAAG,CAAC/B;QAChD,IAAI,CAACb,QAAQ;QAEb,KAAK,MAAM,EAAEuB,MAAM,EAAEO,YAAY,EAAEhB,KAAK,EAAE,IAAId,OAAQ;YACpD,MAAM,IAAI,CAACe,SAAS,CAAClB,IAAI,4BAA4B;gBACnDgB;gBACAU;gBACAO;gBACAhB;YACF;YACA,IAAI,CAACtB,MAAM,CAACwB,KAAK,CACf,kCACA,CAAC,MAAM,EAAEH,WAAW,EACpB,CAAC,OAAO,EAAEU,QAAQ,EAClB,CAAC,SAAS,EAAEO,cAAc,EAC1B,CAAC,WAAW,EAAEhB,OAAO;QAEzB;IACF;IAEQ6D,mBAAmBC,UAAmC,EAAQ;QACpE,MAAMC,aAAa,IAAIC,gDAAuB,CAAC,CAACjE;YAC9C,IAAI,CAACkE,kBAAkB,CAAClE;QAC1B;QACA,IAAI,CAACmE,uBAAuB,CAACJ,YAAY/B,IAAI,CAACgC;QAC9C,IAAI,CAACI,cAAc,CAACJ,YAAYD;QAChC,IAAI,CAACpF,MAAM,CAAC0F,IAAI,CACd,4CACA,CAAC,SAAS,EAAE,IAAI,CAACxF,OAAO,IAAI;IAEhC;IAEQyF,aACNP,UAAmC,EACT;QAC1B,OAAOA,sBAAsBQ,mBAAU;IACzC;IAEQJ,wBACNJ,UAAmC,EACQ;QAC3C,OAAO,AAACA,WAELS,WAAW;IAChB;IAEQJ,eACNJ,UAAmC,EACnCD,UAAmC,EAC7B;QACN,MAAMU,YAAYT;QAClB,IAAI,IAAI,CAACM,YAAY,CAACP,aAAa;YACjCU,UAAUC,aAAa,GAAGX;YAC1B;QACF;QACAU,UAAUE,aAAa,GAAGZ;IAC5B;IAEQ3B,qBAA8B;QACpC,OACE,IAAI,CAACwC,OAAO,CAACC,uBAAuB,KACpCC,8BAAuB,CAACC,UAAU;IAEtC;IAEQ5C,sBAAgC;QACtC,MAAMhD,SAAS;eAAI,IAAI,CAACA,MAAM;SAAC;QAC/B,IAAI,CAAC,IAAI,CAACiD,kBAAkB,IAAI;YAC9B,OAAOjD;QACT;QACA,IAAI,IAAI,CAACkD,aAAa,CAAC1C,IAAI,KAAK,GAAG;YACjC,OAAOR;QACT;QACA,MAAM6F,UAAU,IAAI5B,IAAI,IAAI,CAACf,aAAa;QAC1C,MAAM4C,WAAW9F,OAAO+F,MAAM,CAAC,CAACC,QAAUH,QAAQnD,GAAG,CAACsD;QACtD,IAAIF,SAASnF,MAAM,KAAK,GAAG;YACzB,OAAOX;QACT;QACA,IAAI,CAACR,MAAM,CAACwB,KAAK,CACf,2CACA,CAAC,eAAe,EAAE8E,SAASnF,MAAM,EAAE,EACnC,CAAC,aAAa,EAAEX,OAAOW,MAAM,EAAE;QAEjC,OAAOmF;IACT;IAEOf,mBAAmBlE,SAAiB,EAAQ;QACjD,IAAI,CAAC,IAAI,CAACoC,kBAAkB,IAAI;YAC9B;QACF;QACA,MAAMgD,aAAa,IAAI,CAAC/C,aAAa,CAACR,GAAG,CAAC7B;QAC1C,IAAI,CAACqC,aAAa,CAACoB,GAAG,CAACzD;QACvB,IAAI,CAACoF,YAAY;YACf,IAAI,CAACzG,MAAM,CAACwB,KAAK,CACf,4BACA,CAAC,MAAM,EAAEH,WAAW,EACpB,CAAC,eAAe,EAAE,IAAI,CAACqC,aAAa,CAAC1C,IAAI,EAAE;QAE/C;IACF;IAEQ0F,4BACNC,OAAkC,EACN;QAC5B,IAAI,OAAOA,YAAY,WAAW;YAChC,OAAO;gBAAEC,SAASD;YAAQ;QAC5B;QACA,IAAI,CAACA,SAAS;YACZ,OAAO/C;QACT;QACA,IAAI+C,QAAQC,OAAO,KAAKhD,WAAW;YACjC,OAAO;gBAAE,GAAG+C,OAAO;gBAAEC,SAAS;YAAK;QACrC;QACA,OAAOD;IACT;IAxfA,YACEvB,UAAmC,EACnCa,OAA0B,CAC1B;QACA,KAAK,CAACb,WAAWa,OAAO,CAACY,IAAI,GAZ/B,uBAAQ1G,WAAR,KAAA,IACA,uBAAQK,UAAsB,IAAIiE,QAClC,uBAAQxD,2BAA0D,IAAI6F,QACtE,uBAAQxC,iBAAyB,QACjC,uBAAiB2B,WAAjB,KAAA,IACA,uBAAiBvC,iBAA6B,IAAIe,QAClD,uBAAiBzE,UAAjB,KAAA;QAOE,MAAM+G,uBAAuB,IAAI,CAACL,2BAA2B,CAACT,SAASU;QACvE,MAAMK,kBAAkBC,IAAAA,yBAAgB,EAACF;QACzC,IAAI,CAAC/G,MAAM,GAAGkH,IAAAA,2BAAkB,EAAC;QACjC,IAAI,CAAC/G,OAAO,GAAGiF,WAAWjF,OAAO;QACjC,IAAI,CAAC8F,OAAO,GAAG;YACbC,yBACED,SAASC,2BAA2BC,8BAAuB,CAACgB,IAAI;QACpE;QACA,MAAMC,eACJJ,gBAAgBK,MAAM,KAAKzD,YACvB0D,8BAAqB,CAACN,gBAAgBK,MAAM,CAAC,GAC7CzD;QACN,MAAM2D,eACJP,gBAAgBQ,MAAM,IAAIR,gBAAgBQ,MAAM,CAACrG,MAAM,GAAG,IACtD6F,gBAAgBQ,MAAM,GACtB5D;QACN,MAAM6D,eAAeL,gBAAgBG,eACjCA,aAAahB,MAAM,CAAC,CAACmB,QAAUN,aAAahD,QAAQ,CAACsD,UACrDN,gBAAgBG,gBAAgBI,+BAAsB;QAC1D,MAAMC,oBAAoBH,aAAarG,GAAG,CACxC,CAACsG,QAAUG,6BAAoB,CAACH,MAAM;QAExC,MAAMI,aACJd,gBAAgBK,MAAM,KAAKzD,YACvB,CAAC,MAAM,EACLoD,gBAAgBK,MAAM,KAAKU,2BAAkB,CAACC,MAAM,GAChD,WACA,YACJ,GACFpE;QACN,MAAMqE,kBAAkBV,eACpB,CAAC,gBAAgB,EAAEA,aAChBnG,GAAG,CAAC,CAACsG,QAAUG,6BAAoB,CAACH,MAAM,EAC1CQ,IAAI,CAAC,OAAO,GACftE;QACJ,MAAMuE,kBACJf,gBAAgBG,gBAAgBE,aAAatG,MAAM,KAAK,IACpD,uBACA,CAAC,cAAc,EAAEyG,kBAAkBM,IAAI,CAAC,OAAO;QACrD,MAAME,iBAAiB;YACrBN;YACAG;YACAE;YACA,CAAC,SAAS,EAAE,IAAI,CAACjI,OAAO,IAAI;YAC5B,CAAC,iBAAiB,EAAE,IAAI,CAAC+F,OAAO,CAACC,uBAAuB,EAAE;SAC3D,CAACK,MAAM,CAAC,CAAC8B,QAA2BC,QAAQD;QAC7C,IAAIrB,gBAAgBJ,OAAO,EAAE;YAC3B,IAAI,CAAC5G,MAAM,CAACuI,GAAG,CAAC,yBAAyBH;QAC3C,OAAO;YACL,IAAI,CAACpI,MAAM,CAACwI,IAAI,CAAC,0BAA0BJ;QAC7C;QACA,IACE,IAAI,CAACnC,OAAO,CAACC,uBAAuB,KACpCC,8BAAuB,CAACC,UAAU,EAClC;YACA,IAAI,CAACpG,MAAM,CAAC0F,IAAI,CAAC;YACjB,IAAI,CAACP,kBAAkB,CAACC;QAC1B;IACF;AA0bF"}
@@ -1,3 +1,5 @@
1
1
  export * from "./fastypest";
2
2
  export { ChangeDetectionStrategy } from "./types";
3
3
  export type { FastypestOptions } from "./types";
4
+ export { LogLevel, LoggingDetailLevel } from "../logging";
5
+ export type { LoggingOptions } from "../logging";
@@ -2,14 +2,26 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "ChangeDetectionStrategy", {
6
- enumerable: true,
7
- get: function() {
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 () {
8
13
  return _types.ChangeDetectionStrategy;
14
+ },
15
+ get LogLevel () {
16
+ return _logging.LogLevel;
17
+ },
18
+ get LoggingDetailLevel () {
19
+ return _logging.LoggingDetailLevel;
9
20
  }
10
21
  });
11
22
  _export_star(require("./fastypest"), exports);
12
23
  const _types = require("./types");
24
+ const _logging = require("../logging");
13
25
  function _export_star(from, to) {
14
26
  Object.keys(from).forEach(function(k) {
15
27
  if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/index.ts"],"sourcesContent":["export * from \"./fastypest\";\nexport { ChangeDetectionStrategy } from \"./types\";\nexport type { FastypestOptions } from \"./types\";\n"],"names":["ChangeDetectionStrategy"],"mappings":";;;;+BACSA;;;eAAAA,8BAAuB;;;qBADlB;uBAC0B"}
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"}
@@ -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
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/sql-script/sql-script.ts"],"sourcesContent":["import { DataSourceOptions, EntityManager } from \"typeorm\";\nimport { AllowedDataBases, DB_QUERIES, Queries } from \"./queries\";\nimport { QueryPath } from \"./types\";\n\ntype DBTypes = DataSourceOptions[\"type\"];\n\nexport class SQLScript {\n private queries: Queries;\n\n protected constructor(private readonly type: DBTypes) {\n if (!(this.type in DB_QUERIES)) {\n throw new Error(\n `The database type provided is not supported. Please choose from the following: ${Object.keys(\n DB_QUERIES\n )}`\n );\n }\n\n this.queries = DB_QUERIES[this.type as AllowedDataBases];\n }\n\n protected getType(): DBTypes {\n return this.type;\n }\n\n protected execQuery<T = void>(\n em: EntityManager,\n queryPath: QueryPath<Queries>,\n values?: Record<string, string>\n ): T extends void ? Promise<void> : Promise<T[]> {\n const queryObj = queryPath\n .split(\".\")\n .reduce((obj: any, key) => obj[key], this.queries);\n\n let query = queryObj;\n\n if (values) {\n for (const key in values) {\n query = query.replace(\n new RegExp(`{{\\\\s*${key}\\\\s*}}`, \"g\"),\n values[key]\n );\n }\n }\n\n return em.query(query) as T extends void ? Promise<void> : Promise<T[]>;\n }\n}\n"],"names":["SQLScript","getType","type","execQuery","em","queryPath","values","queryObj","split","reduce","obj","key","queries","query","replace","RegExp","DB_QUERIES","Error","Object","keys"],"mappings":";;;;+BAMaA;;;eAAAA;;;yBALyC;;;;;;;;;;;;;;AAK/C,MAAMA;IAeDC,UAAmB;QAC3B,OAAO,IAAI,CAACC,IAAI;IAClB;IAEUC,UACRC,EAAiB,EACjBC,SAA6B,EAC7BC,MAA+B,EACgB;QAC/C,MAAMC,WAAWF,UACdG,KAAK,CAAC,KACNC,MAAM,CAAC,CAACC,KAAUC,MAAQD,GAAG,CAACC,IAAI,EAAE,IAAI,CAACC,OAAO;QAEnD,IAAIC,QAAQN;QAEZ,IAAID,QAAQ;YACV,IAAK,MAAMK,OAAOL,OAAQ;gBACxBO,QAAQA,MAAMC,OAAO,CACnB,IAAIC,OAAO,CAAC,MAAM,EAAEJ,IAAI,MAAM,CAAC,EAAE,MACjCL,MAAM,CAACK,IAAI;YAEf;QACF;QAEA,OAAOP,GAAGS,KAAK,CAACA;IAClB;IArCA,YAAsB,AAAiBX,IAAa,CAAE;;QAFtD,uBAAQU,WAAR,KAAA;aAEuCV,OAAAA;QACrC,IAAI,CAAE,CAAA,IAAI,CAACA,IAAI,IAAIc,mBAAU,AAAD,GAAI;YAC9B,MAAM,IAAIC,MACR,CAAC,+EAA+E,EAAEC,OAAOC,IAAI,CAC3FH,mBAAU,GACT;QAEP;QAEA,IAAI,CAACJ,OAAO,GAAGI,mBAAU,CAAC,IAAI,CAACd,IAAI,CAAqB;IAC1D;AA4BF"}
1
+ {"version":3,"sources":["../../../src/core/sql-script/sql-script.ts"],"sourcesContent":["import { DataSourceOptions, EntityManager } from \"typeorm\";\nimport { AllowedDataBases, DB_QUERIES, Queries } from \"./queries\";\nimport { QueryPath } from \"./types\";\nimport { createScopedLogger } from \"../../logging\";\n\ntype DBTypes = DataSourceOptions[\"type\"];\n\nexport class SQLScript {\n private queries: Queries;\n private readonly scriptLogger = createScopedLogger(\"SQLScript\");\n\n protected constructor(private readonly type: DBTypes) {\n if (!(this.type in DB_QUERIES)) {\n throw new Error(\n `The database type provided is not supported. Please choose from the following: ${Object.keys(\n DB_QUERIES\n )}`\n );\n }\n\n this.queries = DB_QUERIES[this.type as AllowedDataBases];\n }\n\n protected getType(): DBTypes {\n return this.type;\n }\n\n protected execQuery<T = void>(\n em: EntityManager,\n queryPath: QueryPath<Queries>,\n values?: Record<string, string>\n ): T extends void ? Promise<void> : Promise<T[]> {\n const queryObj = queryPath\n .split(\".\")\n .reduce((obj: any, key) => obj[key], this.queries);\n\n let query = queryObj;\n\n if (values) {\n for (const key in values) {\n query = query.replace(\n new RegExp(`{{\\\\s*${key}\\\\s*}}`, \"g\"),\n values[key]\n );\n }\n }\n\n const parameterEntries = values\n ? Object.entries(values).map(([key, value]) => `${key}=${value}`)\n : [];\n this.scriptLogger.debug(\n \"Executing SQL query\",\n `Path ${queryPath}`,\n parameterEntries.length > 0 ? `Parameters ${parameterEntries.join(\", \")}` : undefined\n );\n return em.query(query) as T extends void ? Promise<void> : Promise<T[]>;\n }\n}\n"],"names":["SQLScript","getType","type","execQuery","em","queryPath","values","queryObj","split","reduce","obj","key","queries","query","replace","RegExp","parameterEntries","Object","entries","map","value","scriptLogger","debug","length","join","undefined","createScopedLogger","DB_QUERIES","Error","keys"],"mappings":";;;;+BAOaA;;;eAAAA;;;yBANyC;yBAEnB;;;;;;;;;;;;;;AAI5B,MAAMA;IAgBDC,UAAmB;QAC3B,OAAO,IAAI,CAACC,IAAI;IAClB;IAEUC,UACRC,EAAiB,EACjBC,SAA6B,EAC7BC,MAA+B,EACgB;QAC/C,MAAMC,WAAWF,UACdG,KAAK,CAAC,KACNC,MAAM,CAAC,CAACC,KAAUC,MAAQD,GAAG,CAACC,IAAI,EAAE,IAAI,CAACC,OAAO;QAEnD,IAAIC,QAAQN;QAEZ,IAAID,QAAQ;YACV,IAAK,MAAMK,OAAOL,OAAQ;gBACxBO,QAAQA,MAAMC,OAAO,CACnB,IAAIC,OAAO,CAAC,MAAM,EAAEJ,IAAI,MAAM,CAAC,EAAE,MACjCL,MAAM,CAACK,IAAI;YAEf;QACF;QAEA,MAAMK,mBAAmBV,SACrBW,OAAOC,OAAO,CAACZ,QAAQa,GAAG,CAAC,CAAC,CAACR,KAAKS,MAAM,GAAK,GAAGT,IAAI,CAAC,EAAES,OAAO,IAC9D,EAAE;QACN,IAAI,CAACC,YAAY,CAACC,KAAK,CACrB,uBACA,CAAC,KAAK,EAAEjB,WAAW,EACnBW,iBAAiBO,MAAM,GAAG,IAAI,CAAC,WAAW,EAAEP,iBAAiBQ,IAAI,CAAC,OAAO,GAAGC;QAE9E,OAAOrB,GAAGS,KAAK,CAACA;IAClB;IA7CA,YAAsB,AAAiBX,IAAa,CAAE;;QAHtD,uBAAQU,WAAR,KAAA;QACA,uBAAiBS,gBAAjB,KAAA;aAEuCnB,OAAAA;aAFtBmB,eAAeK,IAAAA,2BAAkB,EAAC;QAGjD,IAAI,CAAE,CAAA,IAAI,CAACxB,IAAI,IAAIyB,mBAAU,AAAD,GAAI;YAC9B,MAAM,IAAIC,MACR,CAAC,+EAA+E,EAAEX,OAAOY,IAAI,CAC3FF,mBAAU,GACT;QAEP;QAEA,IAAI,CAACf,OAAO,GAAGe,mBAAU,CAAC,IAAI,CAACzB,IAAI,CAAqB;IAC1D;AAoCF"}
@@ -1,4 +1,5 @@
1
1
  import { DataSourceOptions } from "typeorm";
2
+ import type { LoggingOptions } from "../logging";
2
3
  export type Table = {
3
4
  name: string;
4
5
  };
@@ -12,6 +13,7 @@ export declare enum ChangeDetectionStrategy {
12
13
  }
13
14
  export type FastypestOptions = {
14
15
  changeDetectionStrategy?: ChangeDetectionStrategy;
16
+ logging?: boolean | LoggingOptions;
15
17
  };
16
18
  export type ColumnsWithAutoIncrement = {
17
19
  column_name: string;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/types.ts"],"sourcesContent":["import { DataSourceOptions } from \"typeorm\";\n\nexport type Table = { name: string };\nexport type DependencyTreeQueryOut = {\n table_name: string;\n level: number;\n};\n\nexport enum ChangeDetectionStrategy {\n None = \"none\",\n Subscriber = \"subscriber\",\n}\n\nexport type FastypestOptions = {\n changeDetectionStrategy?: ChangeDetectionStrategy;\n};\n\nexport type ColumnsWithAutoIncrement = {\n column_name: string;\n column_default: string;\n};\n\nexport type Manager = {\n foreignKey: {\n disable: () => Promise<void>;\n enable: () => Promise<void>;\n };\n restoreOrder: () => Promise<void>;\n};\nexport type ColumnStat = { maxindex: string | null };\nexport type DBType = DataSourceOptions[\"type\"];\nexport type IncrementDetail = {\n column: string;\n sequenceName: string;\n index: string;\n};\n"],"names":["ChangeDetectionStrategy"],"mappings":";;;;+BAQYA;;;eAAAA;;;AAAL,IAAA,AAAKA,iDAAAA;;;WAAAA"}
1
+ {"version":3,"sources":["../../src/core/types.ts"],"sourcesContent":["import { DataSourceOptions } from \"typeorm\";\nimport type { LoggingOptions } from \"../logging\";\n\nexport type Table = { name: string };\nexport type DependencyTreeQueryOut = {\n table_name: string;\n level: number;\n};\n\nexport enum ChangeDetectionStrategy {\n None = \"none\",\n Subscriber = \"subscriber\",\n}\n\nexport type FastypestOptions = {\n changeDetectionStrategy?: ChangeDetectionStrategy;\n logging?: boolean | LoggingOptions;\n};\n\nexport type ColumnsWithAutoIncrement = {\n column_name: string;\n column_default: string;\n};\n\nexport type Manager = {\n foreignKey: {\n disable: () => Promise<void>;\n enable: () => Promise<void>;\n };\n restoreOrder: () => Promise<void>;\n};\nexport type ColumnStat = { maxindex: string | null };\nexport type DBType = DataSourceOptions[\"type\"];\nexport type IncrementDetail = {\n column: string;\n sequenceName: string;\n index: string;\n};\n"],"names":["ChangeDetectionStrategy"],"mappings":";;;;+BASYA;;;eAAAA;;;AAAL,IAAA,AAAKA,iDAAAA;;;WAAAA"}
@@ -0,0 +1,30 @@
1
+ export declare enum LogLevel {
2
+ Error = "error",
3
+ Warn = "warn",
4
+ Log = "notice",
5
+ Info = "info",
6
+ Debug = "debug",
7
+ Verbose = "verbose"
8
+ }
9
+ export declare enum LoggingDetailLevel {
10
+ Simple = "simple",
11
+ Detailed = "detailed"
12
+ }
13
+ export declare const LOGGING_DEFAULT_ENABLED = false;
14
+ export declare const LOGGING_TIMESTAMP_FORMAT = "YYYY-MM-DD HH:mm:ss";
15
+ export declare const LOGGING_LEVEL_WEIGHTS: Record<LogLevel, number>;
16
+ export declare const LOGGING_LEVEL_SEQUENCE: LogLevel[];
17
+ export declare const LOGGING_DETAIL_LEVELS: Record<LoggingDetailLevel, LogLevel[]>;
18
+ export declare const LOGGING_COLORS: Record<LogLevel, string>;
19
+ export declare const LOGGING_LEVEL_ICONS: Record<LogLevel, string>;
20
+ export declare const LOGGING_LEVEL_LABELS: Record<LogLevel, string>;
21
+ export type LoggingOptions = {
22
+ enabled?: boolean;
23
+ levels?: LogLevel[];
24
+ detail?: LoggingDetailLevel;
25
+ };
26
+ export type ResolvedLoggingOptions = {
27
+ enabled: boolean;
28
+ levels?: LogLevel[];
29
+ detail?: LoggingDetailLevel;
30
+ };
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
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 LOGGING_COLORS () {
13
+ return LOGGING_COLORS;
14
+ },
15
+ get LOGGING_DEFAULT_ENABLED () {
16
+ return LOGGING_DEFAULT_ENABLED;
17
+ },
18
+ get LOGGING_DETAIL_LEVELS () {
19
+ return LOGGING_DETAIL_LEVELS;
20
+ },
21
+ get LOGGING_LEVEL_ICONS () {
22
+ return LOGGING_LEVEL_ICONS;
23
+ },
24
+ get LOGGING_LEVEL_LABELS () {
25
+ return LOGGING_LEVEL_LABELS;
26
+ },
27
+ get LOGGING_LEVEL_SEQUENCE () {
28
+ return LOGGING_LEVEL_SEQUENCE;
29
+ },
30
+ get LOGGING_LEVEL_WEIGHTS () {
31
+ return LOGGING_LEVEL_WEIGHTS;
32
+ },
33
+ get LOGGING_TIMESTAMP_FORMAT () {
34
+ return LOGGING_TIMESTAMP_FORMAT;
35
+ },
36
+ get LogLevel () {
37
+ return LogLevel;
38
+ },
39
+ get LoggingDetailLevel () {
40
+ return LoggingDetailLevel;
41
+ }
42
+ });
43
+ var LogLevel = /*#__PURE__*/ function(LogLevel) {
44
+ LogLevel["Error"] = "error";
45
+ LogLevel["Warn"] = "warn";
46
+ LogLevel["Log"] = "notice";
47
+ LogLevel["Info"] = "info";
48
+ LogLevel["Debug"] = "debug";
49
+ LogLevel["Verbose"] = "verbose";
50
+ return LogLevel;
51
+ }({});
52
+ var LoggingDetailLevel = /*#__PURE__*/ function(LoggingDetailLevel) {
53
+ LoggingDetailLevel["Simple"] = "simple";
54
+ LoggingDetailLevel["Detailed"] = "detailed";
55
+ return LoggingDetailLevel;
56
+ }({});
57
+ const LOGGING_DEFAULT_ENABLED = false;
58
+ const LOGGING_TIMESTAMP_FORMAT = "YYYY-MM-DD HH:mm:ss";
59
+ const LOGGING_LEVEL_WEIGHTS = {
60
+ ["error"]: 0,
61
+ ["warn"]: 1,
62
+ ["notice"]: 2,
63
+ ["info"]: 3,
64
+ ["debug"]: 4,
65
+ ["verbose"]: 5
66
+ };
67
+ const LOGGING_LEVEL_SEQUENCE = [
68
+ "error",
69
+ "warn",
70
+ "notice",
71
+ "info",
72
+ "debug",
73
+ "verbose"
74
+ ];
75
+ const LOGGING_DETAIL_LEVELS = {
76
+ ["simple"]: [
77
+ "error",
78
+ "warn",
79
+ "notice",
80
+ "info"
81
+ ],
82
+ ["detailed"]: [
83
+ ...LOGGING_LEVEL_SEQUENCE
84
+ ]
85
+ };
86
+ const LOGGING_COLORS = {
87
+ ["error"]: "bold red",
88
+ ["warn"]: "bold yellow",
89
+ ["notice"]: "bold green",
90
+ ["info"]: "bold cyan",
91
+ ["debug"]: "bold magenta",
92
+ ["verbose"]: "bold blue"
93
+ };
94
+ const LOGGING_LEVEL_ICONS = {
95
+ ["error"]: "❌",
96
+ ["warn"]: "⚠️",
97
+ ["notice"]: "🟢",
98
+ ["info"]: "💡",
99
+ ["debug"]: "🧭",
100
+ ["verbose"]: "🌀"
101
+ };
102
+ const LOGGING_LEVEL_LABELS = {
103
+ ["error"]: "ERROR",
104
+ ["warn"]: "WARN",
105
+ ["notice"]: "LOG",
106
+ ["info"]: "INFO",
107
+ ["debug"]: "DEBUG",
108
+ ["verbose"]: "VERBOSE"
109
+ };
110
+
111
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/logging/constants.ts"],"sourcesContent":["export enum LogLevel {\n Error = \"error\",\n Warn = \"warn\",\n Log = \"notice\",\n Info = \"info\",\n Debug = \"debug\",\n Verbose = \"verbose\",\n}\n\nexport enum LoggingDetailLevel {\n Simple = \"simple\",\n Detailed = \"detailed\",\n}\n\nexport const LOGGING_DEFAULT_ENABLED = false;\nexport const LOGGING_TIMESTAMP_FORMAT = \"YYYY-MM-DD HH:mm:ss\";\n\nexport const LOGGING_LEVEL_WEIGHTS: Record<LogLevel, number> = {\n [LogLevel.Error]: 0,\n [LogLevel.Warn]: 1,\n [LogLevel.Log]: 2,\n [LogLevel.Info]: 3,\n [LogLevel.Debug]: 4,\n [LogLevel.Verbose]: 5,\n};\n\nexport const LOGGING_LEVEL_SEQUENCE: LogLevel[] = [\n LogLevel.Error,\n LogLevel.Warn,\n LogLevel.Log,\n LogLevel.Info,\n LogLevel.Debug,\n LogLevel.Verbose,\n];\n\nexport const LOGGING_DETAIL_LEVELS: Record<LoggingDetailLevel, LogLevel[]> = {\n [LoggingDetailLevel.Simple]: [\n LogLevel.Error,\n LogLevel.Warn,\n LogLevel.Log,\n LogLevel.Info,\n ],\n [LoggingDetailLevel.Detailed]: [...LOGGING_LEVEL_SEQUENCE],\n};\n\nexport const LOGGING_COLORS: Record<LogLevel, string> = {\n [LogLevel.Error]: \"bold red\",\n [LogLevel.Warn]: \"bold yellow\",\n [LogLevel.Log]: \"bold green\",\n [LogLevel.Info]: \"bold cyan\",\n [LogLevel.Debug]: \"bold magenta\",\n [LogLevel.Verbose]: \"bold blue\",\n};\n\nexport const LOGGING_LEVEL_ICONS: Record<LogLevel, string> = {\n [LogLevel.Error]: \"❌\",\n [LogLevel.Warn]: \"⚠️\",\n [LogLevel.Log]: \"🟢\",\n [LogLevel.Info]: \"💡\",\n [LogLevel.Debug]: \"🧭\",\n [LogLevel.Verbose]: \"🌀\",\n};\n\nexport const LOGGING_LEVEL_LABELS: Record<LogLevel, string> = {\n [LogLevel.Error]: \"ERROR\",\n [LogLevel.Warn]: \"WARN\",\n [LogLevel.Log]: \"LOG\",\n [LogLevel.Info]: \"INFO\",\n [LogLevel.Debug]: \"DEBUG\",\n [LogLevel.Verbose]: \"VERBOSE\",\n};\n\nexport type LoggingOptions = {\n enabled?: boolean;\n levels?: LogLevel[];\n detail?: LoggingDetailLevel;\n};\n\nexport type ResolvedLoggingOptions = {\n enabled: boolean;\n levels?: LogLevel[];\n detail?: LoggingDetailLevel;\n};\n"],"names":["LOGGING_COLORS","LOGGING_DEFAULT_ENABLED","LOGGING_DETAIL_LEVELS","LOGGING_LEVEL_ICONS","LOGGING_LEVEL_LABELS","LOGGING_LEVEL_SEQUENCE","LOGGING_LEVEL_WEIGHTS","LOGGING_TIMESTAMP_FORMAT","LogLevel","LoggingDetailLevel"],"mappings":";;;;;;;;;;;QA6CaA;eAAAA;;QA/BAC;eAAAA;;QAqBAC;eAAAA;;QAmBAC;eAAAA;;QASAC;eAAAA;;QArCAC;eAAAA;;QATAC;eAAAA;;QAFAC;eAAAA;;QAfDC;eAAAA;;QASAC;eAAAA;;;AATL,IAAA,AAAKD,kCAAAA;;;;;;;WAAAA;;AASL,IAAA,AAAKC,4CAAAA;;;WAAAA;;AAKL,MAAMR,0BAA0B;AAChC,MAAMM,2BAA2B;AAEjC,MAAMD,wBAAkD;IAC7D,SAAgB,EAAE;IAClB,QAAe,EAAE;IACjB,UAAc,EAAE;IAChB,QAAe,EAAE;IACjB,SAAgB,EAAE;IAClB,WAAkB,EAAE;AACtB;AAEO,MAAMD,yBAAqC;;;;;;;CAOjD;AAEM,MAAMH,wBAAgE;IAC3E,UAA2B,EAAE;;;;;KAK5B;IACD,YAA6B,EAAE;WAAIG;KAAuB;AAC5D;AAEO,MAAML,iBAA2C;IACtD,SAAgB,EAAE;IAClB,QAAe,EAAE;IACjB,UAAc,EAAE;IAChB,QAAe,EAAE;IACjB,SAAgB,EAAE;IAClB,WAAkB,EAAE;AACtB;AAEO,MAAMG,sBAAgD;IAC3D,SAAgB,EAAE;IAClB,QAAe,EAAE;IACjB,UAAc,EAAE;IAChB,QAAe,EAAE;IACjB,SAAgB,EAAE;IAClB,WAAkB,EAAE;AACtB;AAEO,MAAMC,uBAAiD;IAC5D,SAAgB,EAAE;IAClB,QAAe,EAAE;IACjB,UAAc,EAAE;IAChB,QAAe,EAAE;IACjB,SAAgB,EAAE;IAClB,WAAkB,EAAE;AACtB"}
@@ -0,0 +1,2 @@
1
+ export { configureLogging, createScopedLogger, ScopedLogger, getLoggingOptions, } from "./logger";
2
+ export { LogLevel, LOGGING_DEFAULT_ENABLED, LOGGING_LEVEL_LABELS, LOGGING_LEVEL_SEQUENCE, LOGGING_DETAIL_LEVELS, LoggingDetailLevel, type LoggingOptions, type ResolvedLoggingOptions, } from "./constants";
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
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 LOGGING_DEFAULT_ENABLED () {
13
+ return _constants.LOGGING_DEFAULT_ENABLED;
14
+ },
15
+ get LOGGING_DETAIL_LEVELS () {
16
+ return _constants.LOGGING_DETAIL_LEVELS;
17
+ },
18
+ get LOGGING_LEVEL_LABELS () {
19
+ return _constants.LOGGING_LEVEL_LABELS;
20
+ },
21
+ get LOGGING_LEVEL_SEQUENCE () {
22
+ return _constants.LOGGING_LEVEL_SEQUENCE;
23
+ },
24
+ get LogLevel () {
25
+ return _constants.LogLevel;
26
+ },
27
+ get LoggingDetailLevel () {
28
+ return _constants.LoggingDetailLevel;
29
+ },
30
+ get ScopedLogger () {
31
+ return _logger.ScopedLogger;
32
+ },
33
+ get configureLogging () {
34
+ return _logger.configureLogging;
35
+ },
36
+ get createScopedLogger () {
37
+ return _logger.createScopedLogger;
38
+ },
39
+ get getLoggingOptions () {
40
+ return _logger.getLoggingOptions;
41
+ }
42
+ });
43
+ const _logger = require("./logger");
44
+ const _constants = require("./constants");
45
+
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/logging/index.ts"],"sourcesContent":["export {\n configureLogging,\n createScopedLogger,\n ScopedLogger,\n getLoggingOptions,\n} from \"./logger\";\nexport {\n LogLevel,\n LOGGING_DEFAULT_ENABLED,\n LOGGING_LEVEL_LABELS,\n LOGGING_LEVEL_SEQUENCE,\n LOGGING_DETAIL_LEVELS,\n LoggingDetailLevel,\n type LoggingOptions,\n type ResolvedLoggingOptions,\n} from \"./constants\";\n"],"names":["LOGGING_DEFAULT_ENABLED","LOGGING_DETAIL_LEVELS","LOGGING_LEVEL_LABELS","LOGGING_LEVEL_SEQUENCE","LogLevel","LoggingDetailLevel","ScopedLogger","configureLogging","createScopedLogger","getLoggingOptions"],"mappings":";;;;;;;;;;;QAQEA;eAAAA,kCAAuB;;QAGvBC;eAAAA,gCAAqB;;QAFrBC;eAAAA,+BAAoB;;QACpBC;eAAAA,iCAAsB;;QAHtBC;eAAAA,mBAAQ;;QAKRC;eAAAA,6BAAkB;;QATlBC;eAAAA,oBAAY;;QAFZC;eAAAA,wBAAgB;;QAChBC;eAAAA,0BAAkB;;QAElBC;eAAAA,yBAAiB;;;wBACZ;2BAUA"}
@@ -0,0 +1,32 @@
1
+ import { LogLevel, type LoggingOptions, type ResolvedLoggingOptions } from "./constants";
2
+ type LogDetail = string | number | boolean | bigint | Date | Error | null | undefined;
3
+ type LogDetailsInput = LogDetail | LogDetail[];
4
+ type TimerEmitter = (level: LogLevel, message: string, details: LogDetail[]) => void;
5
+ export declare const configureLogging: (options?: LoggingOptions) => ResolvedLoggingOptions;
6
+ export declare class LoggerTimer {
7
+ private readonly label;
8
+ private readonly emit;
9
+ private readonly start;
10
+ private lastMark;
11
+ private finished;
12
+ constructor(label: string, emit: TimerEmitter);
13
+ mark(message: string, level?: LogLevel, ...details: LogDetailsInput[]): void;
14
+ end(message?: string, level?: LogLevel, ...details: LogDetailsInput[]): void;
15
+ }
16
+ export declare class ScopedLogger {
17
+ private readonly scope;
18
+ private readonly localOptions?;
19
+ constructor(scope: string, localOptions?: LoggingOptions | undefined);
20
+ error(message: string, ...details: LogDetailsInput[]): void;
21
+ warn(message: string, ...details: LogDetailsInput[]): void;
22
+ log(message: string, ...details: LogDetailsInput[]): void;
23
+ info(message: string, ...details: LogDetailsInput[]): void;
24
+ debug(message: string, ...details: LogDetailsInput[]): void;
25
+ verbose(message: string, ...details: LogDetailsInput[]): void;
26
+ timer(label: string): LoggerTimer;
27
+ formatDuration(durationMs: number): string;
28
+ private write;
29
+ }
30
+ export declare const createScopedLogger: (scope: string, options?: LoggingOptions) => ScopedLogger;
31
+ export declare const getLoggingOptions: () => ResolvedLoggingOptions;
32
+ export {};
@@ -0,0 +1,371 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
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 LoggerTimer () {
13
+ return LoggerTimer;
14
+ },
15
+ get ScopedLogger () {
16
+ return ScopedLogger;
17
+ },
18
+ get configureLogging () {
19
+ return configureLogging;
20
+ },
21
+ get createScopedLogger () {
22
+ return createScopedLogger;
23
+ },
24
+ get getLoggingOptions () {
25
+ return getLoggingOptions;
26
+ }
27
+ });
28
+ const _nodeperf_hooks = require("node:perf_hooks");
29
+ const _winston = require("winston");
30
+ const _constants = require("./constants");
31
+ function _define_property(obj, key, value) {
32
+ if (key in obj) {
33
+ Object.defineProperty(obj, key, {
34
+ value: value,
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true
38
+ });
39
+ } else {
40
+ obj[key] = value;
41
+ }
42
+ return obj;
43
+ }
44
+ const LOG_FIELD_LABEL = "label";
45
+ const LOG_FIELD_MESSAGE = "message";
46
+ const LOG_FIELD_LEVEL = "level";
47
+ const LOG_FIELD_TIMESTAMP = "timestamp";
48
+ const LOG_FIELD_DETAILS = "details";
49
+ const ANSI_ESCAPE_PATTERN = /\u001b\[[0-9;]*m/g;
50
+ const DETAIL_SEPARATOR = " · ";
51
+ const DETAIL_PREFIX = " — ";
52
+ const MILLISECONDS_IN_SECOND = 1000;
53
+ const SECONDS_IN_MINUTE = 60;
54
+ const MINUTES_IN_HOUR = 60;
55
+ const MILLISECONDS_IN_MINUTE = MILLISECONDS_IN_SECOND * SECONDS_IN_MINUTE;
56
+ const MILLISECONDS_IN_HOUR = MILLISECONDS_IN_MINUTE * MINUTES_IN_HOUR;
57
+ const DECIMAL_PRECISION_SHORT = 2;
58
+ const DECIMAL_PRECISION_LONG = 1;
59
+ const LOGGING_LEVELS_KEY = "levels";
60
+ const LOGGING_DETAIL_KEY = "detail";
61
+ const formatDetailValue = (detail)=>{
62
+ if (detail === undefined) {
63
+ return undefined;
64
+ }
65
+ if (detail === null) {
66
+ return "null";
67
+ }
68
+ if (detail instanceof Date) {
69
+ return detail.toISOString();
70
+ }
71
+ if (detail instanceof Error) {
72
+ return detail.message;
73
+ }
74
+ if (typeof detail === "boolean") {
75
+ return detail ? "yes" : "no";
76
+ }
77
+ return String(detail);
78
+ };
79
+ const trimDecimals = (value)=>{
80
+ if (Number.isInteger(value)) {
81
+ return value.toString();
82
+ }
83
+ return value.toString();
84
+ };
85
+ const formatSeconds = (seconds)=>{
86
+ const precision = seconds < 10 ? DECIMAL_PRECISION_SHORT : DECIMAL_PRECISION_LONG;
87
+ const rounded = Number(seconds.toFixed(precision));
88
+ return `${trimDecimals(rounded)}s`;
89
+ };
90
+ const formatDurationText = (durationMs)=>{
91
+ if (durationMs <= 0) {
92
+ return "0ms";
93
+ }
94
+ const segments = [];
95
+ const hours = Math.floor(durationMs / MILLISECONDS_IN_HOUR);
96
+ let remaining = durationMs - hours * MILLISECONDS_IN_HOUR;
97
+ const minutes = Math.floor(remaining / MILLISECONDS_IN_MINUTE);
98
+ remaining -= minutes * MILLISECONDS_IN_MINUTE;
99
+ const seconds = remaining / MILLISECONDS_IN_SECOND;
100
+ const wholeSeconds = Math.floor(seconds);
101
+ const leftoverMs = Math.round(remaining - wholeSeconds * MILLISECONDS_IN_SECOND);
102
+ if (hours > 0) {
103
+ segments.push(`${hours}h`);
104
+ }
105
+ if (minutes > 0) {
106
+ segments.push(`${minutes}m`);
107
+ }
108
+ if (hours > 0 || minutes > 0) {
109
+ if (wholeSeconds > 0) {
110
+ segments.push(`${wholeSeconds}s`);
111
+ }
112
+ if (segments.length === 0 || leftoverMs > 0) {
113
+ if (leftoverMs > 0) {
114
+ segments.push(`${leftoverMs}ms`);
115
+ }
116
+ }
117
+ } else if (seconds >= 1) {
118
+ segments.push(formatSeconds(seconds));
119
+ } else {
120
+ segments.push(`${Math.round(durationMs)}ms`);
121
+ }
122
+ return segments.join(" ");
123
+ };
124
+ const extractLevel = (info)=>{
125
+ const levelText = info[LOG_FIELD_LEVEL] ?? info.level;
126
+ if (!levelText) {
127
+ return undefined;
128
+ }
129
+ const normalized = levelText.replace(ANSI_ESCAPE_PATTERN, "").toLowerCase();
130
+ return normalized in _constants.LOGGING_LEVEL_WEIGHTS ? normalized : undefined;
131
+ };
132
+ const formatDetails = (details)=>{
133
+ const formatted = details.map((detail)=>formatDetailValue(detail)).filter((value)=>Boolean(value && value.length > 0));
134
+ if (formatted.length === 0) {
135
+ return undefined;
136
+ }
137
+ return formatted.join(DETAIL_SEPARATOR);
138
+ };
139
+ const formatLogMessage = (info)=>{
140
+ const label = info[LOG_FIELD_LABEL];
141
+ const timestamp = info[LOG_FIELD_TIMESTAMP];
142
+ const level = extractLevel(info);
143
+ const fallbackLevel = info.level.replace(ANSI_ESCAPE_PATTERN, "").toUpperCase();
144
+ const message = info[LOG_FIELD_MESSAGE] ? String(info[LOG_FIELD_MESSAGE]) : info.message;
145
+ const levelLabel = level ? _constants.LOGGING_LEVEL_LABELS[level] : fallbackLevel;
146
+ const levelIcon = level ? `${_constants.LOGGING_LEVEL_ICONS[level]} ` : "";
147
+ const detailText = info[LOG_FIELD_DETAILS] ? String(info[LOG_FIELD_DETAILS]) : "";
148
+ const formattedDetails = detailText ? `${DETAIL_PREFIX}${detailText}` : "";
149
+ const timestampText = timestamp ? `${timestamp} ` : "";
150
+ return `${timestampText}${levelIcon}[${label ?? ""}] ${levelLabel} ${message}${formattedDetails}`;
151
+ };
152
+ (0, _winston.addColors)(_constants.LOGGING_COLORS);
153
+ const baseLogger = (0, _winston.createLogger)({
154
+ levels: _constants.LOGGING_LEVEL_WEIGHTS,
155
+ level: _constants.LogLevel.Verbose,
156
+ format: _winston.format.combine(_winston.format.timestamp({
157
+ format: _constants.LOGGING_TIMESTAMP_FORMAT
158
+ }), _winston.format.colorize({
159
+ all: true
160
+ }), _winston.format.printf((info)=>formatLogMessage(info))),
161
+ transports: [
162
+ new _winston.transports.Console()
163
+ ],
164
+ silent: false
165
+ });
166
+ let globalOptions = {
167
+ enabled: _constants.LOGGING_DEFAULT_ENABLED,
168
+ levels: undefined,
169
+ detail: undefined
170
+ };
171
+ const resolveEnabled = (enabled, hasOptions)=>{
172
+ if (enabled !== undefined) {
173
+ return enabled;
174
+ }
175
+ if (hasOptions) {
176
+ return true;
177
+ }
178
+ return _constants.LOGGING_DEFAULT_ENABLED;
179
+ };
180
+ const normalizeLevels = (levels)=>{
181
+ if (!levels || levels.length === 0) {
182
+ return undefined;
183
+ }
184
+ const unique = Array.from(new Set(levels));
185
+ return unique.length > 0 ? unique : undefined;
186
+ };
187
+ const hasLevelsOption = (options)=>{
188
+ if (!options) {
189
+ return false;
190
+ }
191
+ return Object.prototype.hasOwnProperty.call(options, LOGGING_LEVELS_KEY);
192
+ };
193
+ const resolveLoggingOptions = (options)=>{
194
+ const hasOptions = Boolean(options);
195
+ const enabled = resolveEnabled(options?.enabled, hasOptions);
196
+ if (!enabled) {
197
+ return {
198
+ enabled,
199
+ levels: undefined,
200
+ detail: undefined
201
+ };
202
+ }
203
+ return {
204
+ enabled,
205
+ levels: normalizeLevels(options?.levels),
206
+ detail: options?.detail
207
+ };
208
+ };
209
+ const getDetailLevels = (detail)=>{
210
+ if (!detail) {
211
+ return undefined;
212
+ }
213
+ return _constants.LOGGING_DETAIL_LEVELS[detail];
214
+ };
215
+ const shouldLog = (level, options)=>{
216
+ if (!options.enabled) {
217
+ return false;
218
+ }
219
+ const detailLevels = getDetailLevels(options.detail);
220
+ const hasDetailFilter = detailLevels && detailLevels.length > 0;
221
+ const hasLevelFilter = options.levels && options.levels.length > 0;
222
+ if (!hasDetailFilter && !hasLevelFilter) {
223
+ return true;
224
+ }
225
+ if (hasDetailFilter && !detailLevels.includes(level)) {
226
+ return false;
227
+ }
228
+ if (hasLevelFilter && !options.levels.includes(level)) {
229
+ return false;
230
+ }
231
+ return true;
232
+ };
233
+ const mergeOptions = (local)=>{
234
+ if (!local) {
235
+ return globalOptions;
236
+ }
237
+ const resolvedLocal = resolveLoggingOptions(local);
238
+ const hasLocalLevels = hasLevelsOption(local);
239
+ const hasLocalDetail = Object.prototype.hasOwnProperty.call(local, LOGGING_DETAIL_KEY);
240
+ const ignoreGlobalLevels = hasLocalDetail && !hasLocalLevels;
241
+ return {
242
+ enabled: resolvedLocal.enabled,
243
+ levels: hasLocalLevels ? resolvedLocal.levels : ignoreGlobalLevels ? undefined : globalOptions.levels,
244
+ detail: hasLocalDetail ? resolvedLocal.detail : globalOptions.detail
245
+ };
246
+ };
247
+ const normalizeDetails = (input)=>{
248
+ return input.flatMap((entry)=>{
249
+ if (Array.isArray(entry)) {
250
+ return entry;
251
+ }
252
+ return [
253
+ entry
254
+ ];
255
+ });
256
+ };
257
+ const logWithDetails = (level, scope, message, details, options)=>{
258
+ if (!shouldLog(level, options)) {
259
+ return;
260
+ }
261
+ const formattedDetails = formatDetails(details);
262
+ const logPayload = {
263
+ level,
264
+ message,
265
+ [LOG_FIELD_LABEL]: scope
266
+ };
267
+ if (formattedDetails) {
268
+ logPayload[LOG_FIELD_DETAILS] = formattedDetails;
269
+ }
270
+ baseLogger.log(logPayload);
271
+ };
272
+ const configureLogging = (options)=>{
273
+ globalOptions = resolveLoggingOptions(options);
274
+ return globalOptions;
275
+ };
276
+ class LoggerTimer {
277
+ mark(message, level = _constants.LogLevel.Debug, ...details) {
278
+ if (this.finished) {
279
+ return;
280
+ }
281
+ const now = _nodeperf_hooks.performance.now();
282
+ const totalElapsed = now - this.start;
283
+ const segmentElapsed = now - this.lastMark;
284
+ this.lastMark = now;
285
+ const timerDetails = [
286
+ `${this.label} total ${formatDurationText(totalElapsed)}`
287
+ ];
288
+ if (segmentElapsed > 0 && segmentElapsed !== totalElapsed) {
289
+ timerDetails.push(`segment ${formatDurationText(segmentElapsed)}`);
290
+ }
291
+ const normalized = normalizeDetails(details);
292
+ this.emit(level, message, [
293
+ ...timerDetails,
294
+ ...normalized
295
+ ]);
296
+ }
297
+ end(message, level = _constants.LogLevel.Info, ...details) {
298
+ if (this.finished) {
299
+ return;
300
+ }
301
+ const totalElapsed = _nodeperf_hooks.performance.now() - this.start;
302
+ const normalized = normalizeDetails(details);
303
+ const timerDetails = [
304
+ `${this.label} total ${formatDurationText(totalElapsed)}`
305
+ ];
306
+ this.emit(level, message ?? `${this.label} completed`, [
307
+ ...timerDetails,
308
+ ...normalized
309
+ ]);
310
+ this.finished = true;
311
+ }
312
+ constructor(label, emit){
313
+ _define_property(this, "label", void 0);
314
+ _define_property(this, "emit", void 0);
315
+ _define_property(this, "start", void 0);
316
+ _define_property(this, "lastMark", void 0);
317
+ _define_property(this, "finished", void 0);
318
+ this.label = label;
319
+ this.emit = emit;
320
+ this.start = _nodeperf_hooks.performance.now();
321
+ this.lastMark = this.start;
322
+ this.finished = false;
323
+ }
324
+ }
325
+ class ScopedLogger {
326
+ error(message, ...details) {
327
+ this.write(_constants.LogLevel.Error, message, details);
328
+ }
329
+ warn(message, ...details) {
330
+ this.write(_constants.LogLevel.Warn, message, details);
331
+ }
332
+ log(message, ...details) {
333
+ this.write(_constants.LogLevel.Log, message, details);
334
+ }
335
+ info(message, ...details) {
336
+ this.write(_constants.LogLevel.Info, message, details);
337
+ }
338
+ debug(message, ...details) {
339
+ this.write(_constants.LogLevel.Debug, message, details);
340
+ }
341
+ verbose(message, ...details) {
342
+ this.write(_constants.LogLevel.Verbose, message, details);
343
+ }
344
+ timer(label) {
345
+ return new LoggerTimer(label, (level, message, details)=>{
346
+ this.write(level, message, details);
347
+ });
348
+ }
349
+ formatDuration(durationMs) {
350
+ return formatDurationText(durationMs);
351
+ }
352
+ write(level, message, details) {
353
+ const normalized = normalizeDetails(details);
354
+ logWithDetails(level, this.scope, message, normalized, mergeOptions(this.localOptions));
355
+ }
356
+ constructor(scope, localOptions){
357
+ _define_property(this, "scope", void 0);
358
+ _define_property(this, "localOptions", void 0);
359
+ this.scope = scope;
360
+ this.localOptions = localOptions;
361
+ }
362
+ }
363
+ const createScopedLogger = (scope, options)=>new ScopedLogger(scope, options);
364
+ const getLoggingOptions = ()=>({
365
+ ...globalOptions,
366
+ levels: globalOptions.levels ? [
367
+ ...globalOptions.levels
368
+ ] : undefined
369
+ });
370
+
371
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/logging/logger.ts"],"sourcesContent":["import { performance } from \"node:perf_hooks\";\nimport { addColors, createLogger, format, transports } from \"winston\";\nimport {\n LOGGING_COLORS,\n LOGGING_DEFAULT_ENABLED,\n LOGGING_DETAIL_LEVELS,\n LOGGING_LEVEL_ICONS,\n LOGGING_LEVEL_LABELS,\n LOGGING_LEVEL_WEIGHTS,\n LOGGING_TIMESTAMP_FORMAT,\n LogLevel,\n LoggingDetailLevel,\n type LoggingOptions,\n type ResolvedLoggingOptions,\n} from \"./constants\";\n\nconst LOG_FIELD_LABEL = \"label\";\nconst LOG_FIELD_MESSAGE = \"message\";\nconst LOG_FIELD_LEVEL = \"level\";\nconst LOG_FIELD_TIMESTAMP = \"timestamp\";\nconst LOG_FIELD_DETAILS = \"details\";\nconst ANSI_ESCAPE_PATTERN = /\\u001b\\[[0-9;]*m/g;\nconst DETAIL_SEPARATOR = \" · \";\nconst DETAIL_PREFIX = \" — \";\nconst MILLISECONDS_IN_SECOND = 1000;\nconst SECONDS_IN_MINUTE = 60;\nconst MINUTES_IN_HOUR = 60;\nconst MILLISECONDS_IN_MINUTE = MILLISECONDS_IN_SECOND * SECONDS_IN_MINUTE;\nconst MILLISECONDS_IN_HOUR = MILLISECONDS_IN_MINUTE * MINUTES_IN_HOUR;\nconst DECIMAL_PRECISION_SHORT = 2;\nconst DECIMAL_PRECISION_LONG = 1;\nconst LOGGING_LEVELS_KEY: keyof LoggingOptions = \"levels\";\nconst LOGGING_DETAIL_KEY: keyof LoggingOptions = \"detail\";\n\nconst formatDetailValue = (detail: LogDetail): string | undefined => {\n if (detail === undefined) {\n return undefined;\n }\n if (detail === null) {\n return \"null\";\n }\n if (detail instanceof Date) {\n return detail.toISOString();\n }\n if (detail instanceof Error) {\n return detail.message;\n }\n if (typeof detail === \"boolean\") {\n return detail ? \"yes\" : \"no\";\n }\n return String(detail);\n};\n\nconst trimDecimals = (value: number): string => {\n if (Number.isInteger(value)) {\n return value.toString();\n }\n return value.toString();\n};\n\nconst formatSeconds = (seconds: number): string => {\n const precision = seconds < 10 ? DECIMAL_PRECISION_SHORT : DECIMAL_PRECISION_LONG;\n const rounded = Number(seconds.toFixed(precision));\n return `${trimDecimals(rounded)}s`;\n};\n\nconst formatDurationText = (durationMs: number): string => {\n if (durationMs <= 0) {\n return \"0ms\";\n }\n const segments: string[] = [];\n const hours = Math.floor(durationMs / MILLISECONDS_IN_HOUR);\n let remaining = durationMs - hours * MILLISECONDS_IN_HOUR;\n const minutes = Math.floor(remaining / MILLISECONDS_IN_MINUTE);\n remaining -= minutes * MILLISECONDS_IN_MINUTE;\n const seconds = remaining / MILLISECONDS_IN_SECOND;\n const wholeSeconds = Math.floor(seconds);\n const leftoverMs = Math.round(remaining - wholeSeconds * MILLISECONDS_IN_SECOND);\n\n if (hours > 0) {\n segments.push(`${hours}h`);\n }\n if (minutes > 0) {\n segments.push(`${minutes}m`);\n }\n if (hours > 0 || minutes > 0) {\n if (wholeSeconds > 0) {\n segments.push(`${wholeSeconds}s`);\n }\n if (segments.length === 0 || leftoverMs > 0) {\n if (leftoverMs > 0) {\n segments.push(`${leftoverMs}ms`);\n }\n }\n } else if (seconds >= 1) {\n segments.push(formatSeconds(seconds));\n } else {\n segments.push(`${Math.round(durationMs)}ms`);\n }\n return segments.join(\" \");\n};\n\ntype LogDetail = string | number | boolean | bigint | Date | Error | null | undefined;\n\ntype LogDetailsInput = LogDetail | LogDetail[];\n\ntype LoggerInfo = Record<string, unknown> & {\n level: string;\n message: string;\n [LOG_FIELD_DETAILS]?: string;\n};\n\ntype LoggerPayload = LoggerInfo & {\n [LOG_FIELD_LABEL]: string;\n};\n\ntype TimerEmitter = (level: LogLevel, message: string, details: LogDetail[]) => void;\n\nconst extractLevel = (info: LoggerInfo): LogLevel | undefined => {\n const levelText = (info[LOG_FIELD_LEVEL] as string | undefined) ?? info.level;\n if (!levelText) {\n return undefined;\n }\n const normalized = levelText.replace(ANSI_ESCAPE_PATTERN, \"\").toLowerCase();\n return normalized in LOGGING_LEVEL_WEIGHTS ? (normalized as LogLevel) : undefined;\n};\n\nconst formatDetails = (details: LogDetail[]): string | undefined => {\n const formatted = details\n .map((detail) => formatDetailValue(detail))\n .filter((value): value is string => Boolean(value && value.length > 0));\n if (formatted.length === 0) {\n return undefined;\n }\n return formatted.join(DETAIL_SEPARATOR);\n};\n\nconst formatLogMessage = (info: LoggerInfo): string => {\n const label = info[LOG_FIELD_LABEL] as string | undefined;\n const timestamp = info[LOG_FIELD_TIMESTAMP] as string | undefined;\n const level = extractLevel(info);\n const fallbackLevel = info.level.replace(ANSI_ESCAPE_PATTERN, \"\").toUpperCase();\n const message = info[LOG_FIELD_MESSAGE] ? String(info[LOG_FIELD_MESSAGE]) : info.message;\n const levelLabel = level ? LOGGING_LEVEL_LABELS[level] : fallbackLevel;\n const levelIcon = level ? `${LOGGING_LEVEL_ICONS[level]} ` : \"\";\n const detailText = info[LOG_FIELD_DETAILS] ? String(info[LOG_FIELD_DETAILS]) : \"\";\n const formattedDetails = detailText ? `${DETAIL_PREFIX}${detailText}` : \"\";\n const timestampText = timestamp ? `${timestamp} ` : \"\";\n return `${timestampText}${levelIcon}[${label ?? \"\"}] ${levelLabel} ${message}${formattedDetails}`;\n};\n\naddColors(LOGGING_COLORS);\n\nconst baseLogger = createLogger({\n levels: LOGGING_LEVEL_WEIGHTS,\n level: LogLevel.Verbose,\n format: format.combine(\n format.timestamp({ format: LOGGING_TIMESTAMP_FORMAT }),\n format.colorize({ all: true }),\n format.printf((info: unknown) => formatLogMessage(info as LoggerInfo))\n ),\n transports: [new transports.Console()],\n silent: false,\n});\n\nlet globalOptions: ResolvedLoggingOptions = {\n enabled: LOGGING_DEFAULT_ENABLED,\n levels: undefined,\n detail: undefined,\n};\n\nconst resolveEnabled = (enabled: boolean | undefined, hasOptions: boolean): boolean => {\n if (enabled !== undefined) {\n return enabled;\n }\n if (hasOptions) {\n return true;\n }\n return LOGGING_DEFAULT_ENABLED;\n};\n\nconst normalizeLevels = (levels?: LogLevel[]): LogLevel[] | undefined => {\n if (!levels || levels.length === 0) {\n return undefined;\n }\n const unique = Array.from(new Set(levels));\n return unique.length > 0 ? unique : undefined;\n};\n\nconst hasLevelsOption = (options?: LoggingOptions): boolean => {\n if (!options) {\n return false;\n }\n return Object.prototype.hasOwnProperty.call(options, LOGGING_LEVELS_KEY);\n};\n\nconst resolveLoggingOptions = (options?: LoggingOptions): ResolvedLoggingOptions => {\n const hasOptions = Boolean(options);\n const enabled = resolveEnabled(options?.enabled, hasOptions);\n if (!enabled) {\n return { enabled, levels: undefined, detail: undefined };\n }\n return {\n enabled,\n levels: normalizeLevels(options?.levels),\n detail: options?.detail,\n };\n};\n\nconst getDetailLevels = (\n detail: LoggingDetailLevel | undefined\n): LogLevel[] | undefined => {\n if (!detail) {\n return undefined;\n }\n return LOGGING_DETAIL_LEVELS[detail];\n};\n\nconst shouldLog = (level: LogLevel, options: ResolvedLoggingOptions): boolean => {\n if (!options.enabled) {\n return false;\n }\n const detailLevels = getDetailLevels(options.detail);\n const hasDetailFilter = detailLevels && detailLevels.length > 0;\n const hasLevelFilter = options.levels && options.levels.length > 0;\n if (!hasDetailFilter && !hasLevelFilter) {\n return true;\n }\n if (hasDetailFilter && !detailLevels!.includes(level)) {\n return false;\n }\n if (hasLevelFilter && !options.levels!.includes(level)) {\n return false;\n }\n return true;\n};\n\nconst mergeOptions = (local?: LoggingOptions): ResolvedLoggingOptions => {\n if (!local) {\n return globalOptions;\n }\n const resolvedLocal = resolveLoggingOptions(local);\n const hasLocalLevels = hasLevelsOption(local);\n const hasLocalDetail = Object.prototype.hasOwnProperty.call(\n local,\n LOGGING_DETAIL_KEY\n );\n const ignoreGlobalLevels = hasLocalDetail && !hasLocalLevels;\n return {\n enabled: resolvedLocal.enabled,\n levels: hasLocalLevels\n ? resolvedLocal.levels\n : ignoreGlobalLevels\n ? undefined\n : globalOptions.levels,\n detail: hasLocalDetail ? resolvedLocal.detail : globalOptions.detail,\n };\n};\n\nconst normalizeDetails = (input: LogDetailsInput[]): LogDetail[] => {\n return input.flatMap((entry) => {\n if (Array.isArray(entry)) {\n return entry;\n }\n return [entry];\n });\n};\n\nconst logWithDetails = (\n level: LogLevel,\n scope: string,\n message: string,\n details: LogDetail[],\n options: ResolvedLoggingOptions\n): void => {\n if (!shouldLog(level, options)) {\n return;\n }\n const formattedDetails = formatDetails(details);\n const logPayload: LoggerPayload = {\n level,\n message,\n [LOG_FIELD_LABEL]: scope,\n };\n if (formattedDetails) {\n logPayload[LOG_FIELD_DETAILS] = formattedDetails;\n }\n baseLogger.log(logPayload);\n};\n\nexport const configureLogging = (options?: LoggingOptions): ResolvedLoggingOptions => {\n globalOptions = resolveLoggingOptions(options);\n return globalOptions;\n};\n\nexport class LoggerTimer {\n private readonly start = performance.now();\n private lastMark = this.start;\n private finished = false;\n\n constructor(\n private readonly label: string,\n private readonly emit: TimerEmitter\n ) {}\n\n public mark(message: string, level: LogLevel = LogLevel.Debug, ...details: LogDetailsInput[]): void {\n if (this.finished) {\n return;\n }\n const now = performance.now();\n const totalElapsed = now - this.start;\n const segmentElapsed = now - this.lastMark;\n this.lastMark = now;\n const timerDetails: LogDetail[] = [\n `${this.label} total ${formatDurationText(totalElapsed)}`,\n ];\n if (segmentElapsed > 0 && segmentElapsed !== totalElapsed) {\n timerDetails.push(`segment ${formatDurationText(segmentElapsed)}`);\n }\n const normalized = normalizeDetails(details);\n this.emit(level, message, [...timerDetails, ...normalized]);\n }\n\n public end(\n message?: string,\n level: LogLevel = LogLevel.Info,\n ...details: LogDetailsInput[]\n ): void {\n if (this.finished) {\n return;\n }\n const totalElapsed = performance.now() - this.start;\n const normalized = normalizeDetails(details);\n const timerDetails: LogDetail[] = [`${this.label} total ${formatDurationText(totalElapsed)}`];\n this.emit(level, message ?? `${this.label} completed`, [...timerDetails, ...normalized]);\n this.finished = true;\n }\n}\n\nexport class ScopedLogger {\n constructor(private readonly scope: string, private readonly localOptions?: LoggingOptions) {}\n\n public error(message: string, ...details: LogDetailsInput[]): void {\n this.write(LogLevel.Error, message, details);\n }\n\n public warn(message: string, ...details: LogDetailsInput[]): void {\n this.write(LogLevel.Warn, message, details);\n }\n\n public log(message: string, ...details: LogDetailsInput[]): void {\n this.write(LogLevel.Log, message, details);\n }\n\n public info(message: string, ...details: LogDetailsInput[]): void {\n this.write(LogLevel.Info, message, details);\n }\n\n public debug(message: string, ...details: LogDetailsInput[]): void {\n this.write(LogLevel.Debug, message, details);\n }\n\n public verbose(message: string, ...details: LogDetailsInput[]): void {\n this.write(LogLevel.Verbose, message, details);\n }\n\n public timer(label: string): LoggerTimer {\n return new LoggerTimer(label, (level, message, details) => {\n this.write(level, message, details);\n });\n }\n\n public formatDuration(durationMs: number): string {\n return formatDurationText(durationMs);\n }\n\n private write(level: LogLevel, message: string, details: LogDetailsInput[]): void {\n const normalized = normalizeDetails(details);\n logWithDetails(level, this.scope, message, normalized, mergeOptions(this.localOptions));\n }\n}\n\nexport const createScopedLogger = (scope: string, options?: LoggingOptions): ScopedLogger =>\n new ScopedLogger(scope, options);\n\nexport const getLoggingOptions = (): ResolvedLoggingOptions => ({\n ...globalOptions,\n levels: globalOptions.levels ? [...globalOptions.levels] : undefined,\n});\n"],"names":["LoggerTimer","ScopedLogger","configureLogging","createScopedLogger","getLoggingOptions","LOG_FIELD_LABEL","LOG_FIELD_MESSAGE","LOG_FIELD_LEVEL","LOG_FIELD_TIMESTAMP","LOG_FIELD_DETAILS","ANSI_ESCAPE_PATTERN","DETAIL_SEPARATOR","DETAIL_PREFIX","MILLISECONDS_IN_SECOND","SECONDS_IN_MINUTE","MINUTES_IN_HOUR","MILLISECONDS_IN_MINUTE","MILLISECONDS_IN_HOUR","DECIMAL_PRECISION_SHORT","DECIMAL_PRECISION_LONG","LOGGING_LEVELS_KEY","LOGGING_DETAIL_KEY","formatDetailValue","detail","undefined","Date","toISOString","Error","message","String","trimDecimals","value","Number","isInteger","toString","formatSeconds","seconds","precision","rounded","toFixed","formatDurationText","durationMs","segments","hours","Math","floor","remaining","minutes","wholeSeconds","leftoverMs","round","push","length","join","extractLevel","info","levelText","level","normalized","replace","toLowerCase","LOGGING_LEVEL_WEIGHTS","formatDetails","details","formatted","map","filter","Boolean","formatLogMessage","label","timestamp","fallbackLevel","toUpperCase","levelLabel","LOGGING_LEVEL_LABELS","levelIcon","LOGGING_LEVEL_ICONS","detailText","formattedDetails","timestampText","addColors","LOGGING_COLORS","baseLogger","createLogger","levels","LogLevel","Verbose","format","combine","LOGGING_TIMESTAMP_FORMAT","colorize","all","printf","transports","Console","silent","globalOptions","enabled","LOGGING_DEFAULT_ENABLED","resolveEnabled","hasOptions","normalizeLevels","unique","Array","from","Set","hasLevelsOption","options","Object","prototype","hasOwnProperty","call","resolveLoggingOptions","getDetailLevels","LOGGING_DETAIL_LEVELS","shouldLog","detailLevels","hasDetailFilter","hasLevelFilter","includes","mergeOptions","local","resolvedLocal","hasLocalLevels","hasLocalDetail","ignoreGlobalLevels","normalizeDetails","input","flatMap","entry","isArray","logWithDetails","scope","logPayload","log","mark","Debug","finished","now","performance","totalElapsed","start","segmentElapsed","lastMark","timerDetails","emit","end","Info","error","write","warn","Warn","Log","debug","verbose","timer","formatDuration","localOptions"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastypest",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
4
4
  "description": "Restores the database automatically after each test. Allows serial execution of tests without having to delete and restore the database having to stop the application",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -49,15 +49,19 @@
49
49
  "url": "https://github.com/juanjoGonDev/fastypest/issues"
50
50
  },
51
51
  "homepage": "https://github.com/juanjoGonDev/fastypest#readme",
52
+ "dependencies": {
53
+ "winston": "^3.14.2"
54
+ },
52
55
  "devDependencies": {
53
56
  "@eslint/js": "^9.36.0",
54
57
  "@swc-node/jest": "^1.9.1",
55
58
  "@swc/cli": "^0.7.8",
56
- "@swc/core": "^1.13.5",
59
+ "@swc/core": "^1.13.19",
57
60
  "@swc/helpers": "^0.5.17",
58
61
  "@types/jest": "^30.0.0",
59
62
  "@types/node": "^24.5.1",
60
- "@typescript-eslint/eslint-plugin": "^8.44.0",
63
+ "@types/winston": "^2.4.4",
64
+ "@typescript-eslint/eslint-plugin": "^8.44.1",
61
65
  "@typescript-eslint/parser": "^8.44.1",
62
66
  "@typescript-eslint/types": "8.44.1",
63
67
  "cpy-cli": "^6.0.0",
@@ -71,7 +75,7 @@
71
75
  "globals": "^16.4.0",
72
76
  "jest": "^30.1.3",
73
77
  "lefthook": "^1.13.4",
74
- "lint-staged": "^16.1.6",
78
+ "lint-staged": "^16.2.1",
75
79
  "mariadb": "^3.4.5",
76
80
  "mysql": "^2.18.1",
77
81
  "pg": "^8.16.3",