@nmakarov/cli-toolkit 0.39.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3263,6 +3263,41 @@ var Db = class _Db {
3263
3263
  }
3264
3264
  return stack.pop();
3265
3265
  };
3266
+ const isTimeoutError = (error) => error?.name === "KnexTimeoutError" || /query timeout|timeout exceeded/i.test(String(error?.message ?? ""));
3267
+ const logQueryEntry = (query, start, { error } = {}) => {
3268
+ let executionTimeMs;
3269
+ if (start) {
3270
+ const [seconds, nanoseconds] = process.hrtime(start);
3271
+ executionTimeMs = (seconds * 1e3 + nanoseconds / 1e6).toFixed(2);
3272
+ } else if (error?.timeout != null) {
3273
+ executionTimeMs = Number(error.timeout).toFixed(2);
3274
+ } else {
3275
+ executionTimeMs = "?";
3276
+ }
3277
+ let status = "ok";
3278
+ if (error) {
3279
+ status = isTimeoutError(error) ? "timeout" : "error";
3280
+ }
3281
+ const logEntry = {
3282
+ sql: query?.sql,
3283
+ bindings: query?.bindings || [],
3284
+ executionTimeMs,
3285
+ status
3286
+ };
3287
+ if (error) {
3288
+ logEntry.error = error.message ?? String(error);
3289
+ }
3290
+ this.queriesLog.push(logEntry);
3291
+ const suffix = error ? ` | ${status}: ${logEntry.error}` : "";
3292
+ this.logger.debug?.(
3293
+ `[Db] Query: ${query?.sql} | Duration: ${executionTimeMs}ms${suffix}`
3294
+ );
3295
+ };
3296
+ const handleQueryError = (error, query) => {
3297
+ const start = popStart(query);
3298
+ logQueryEntry(query, start, { error });
3299
+ this.logger.error?.(`[Db] Query failed: ${query?.sql}`, error);
3300
+ };
3266
3301
  this.knexInstance.on("query", (query) => {
3267
3302
  pushStart(query);
3268
3303
  });
@@ -3271,20 +3306,31 @@ var Db = class _Db {
3271
3306
  if (!start) {
3272
3307
  return;
3273
3308
  }
3274
- const [seconds, nanoseconds] = process.hrtime(start);
3275
- const executionTimeMs = (seconds * 1e3 + nanoseconds / 1e6).toFixed(2);
3276
- const logEntry = {
3277
- sql: query.sql,
3278
- bindings: query.bindings || [],
3279
- executionTimeMs
3280
- };
3281
- this.queriesLog.push(logEntry);
3282
- this.logger.debug?.(`[Db] Query: ${query.sql} | Duration: ${executionTimeMs}ms`);
3309
+ logQueryEntry(query, start);
3283
3310
  });
3284
3311
  this.knexInstance.on("query-error", (error, query) => {
3285
- popStart(query);
3286
- this.logger.error?.(`[Db] Query failed: ${query.sql}`, error);
3312
+ handleQueryError(error, query);
3287
3313
  });
3314
+ const hookBuilder = (builder) => {
3315
+ if (!builder || builder.__dbProfilerHooked) {
3316
+ return;
3317
+ }
3318
+ builder.__dbProfilerHooked = true;
3319
+ builder.on("query", pushStart);
3320
+ builder.on("query-error", handleQueryError);
3321
+ };
3322
+ const client = this.knexInstance.client;
3323
+ if (client && !client.__dbProfilerPatched) {
3324
+ client.__dbProfilerPatched = true;
3325
+ if (typeof client.queryBuilder === "function") {
3326
+ const origQueryBuilder = client.queryBuilder.bind(client);
3327
+ client.queryBuilder = (...args) => {
3328
+ const builder = origQueryBuilder(...args);
3329
+ hookBuilder(builder);
3330
+ return builder;
3331
+ };
3332
+ }
3333
+ }
3288
3334
  }
3289
3335
  getQueryLog() {
3290
3336
  return [...this.queriesLog];
@@ -4020,6 +4066,9 @@ var FileDatabase = class _FileDatabase {
4020
4066
  currentRecord = 0;
4021
4067
  hasReadFirstPage = false;
4022
4068
  lastFileData = null;
4069
+ /** Cache of the last JSON file parsed during paginated reads (avoid re-parse per page). */
4070
+ readFileCache = null;
4071
+ // { filePath: string, data: any[] } | null
4023
4072
  metadata;
4024
4073
  // Synopsis calculation functions
4025
4074
  fileSynopsisFunction = null;
@@ -4786,7 +4835,6 @@ var FileDatabase = class _FileDatabase {
4786
4835
  let effectivePageSize;
4787
4836
  if (nextPage && this.hasReadFirstPage) {
4788
4837
  effectivePageSize = pageSize || this.pageSize;
4789
- this.currentRecord += effectivePageSize;
4790
4838
  } else if (!nextPage) {
4791
4839
  effectivePageSize = pageSize !== void 0 ? pageSize : this.metadata.totalRecords;
4792
4840
  this.currentRecord = 0;
@@ -4815,8 +4863,14 @@ var FileDatabase = class _FileDatabase {
4815
4863
  const file = this.metadata.files[i];
4816
4864
  const filePath = path3.join(this.getDestinationPath(this.currentVersion || void 0), file.fileName);
4817
4865
  try {
4818
- const rawData = await fs3.promises.readFile(filePath, "utf8");
4819
- const fileData = deserializeData(rawData, this.metadata.dataType);
4866
+ let fileData;
4867
+ if (this.readFileCache?.filePath === filePath && Array.isArray(this.readFileCache.data)) {
4868
+ fileData = this.readFileCache.data;
4869
+ } else {
4870
+ const rawData = await fs3.promises.readFile(filePath, "utf8");
4871
+ fileData = deserializeData(rawData, this.metadata.dataType);
4872
+ this.readFileCache = { filePath, data: fileData };
4873
+ }
4820
4874
  let startIndex = 0;
4821
4875
  if (i === currentFileIndex) {
4822
4876
  startIndex = this.currentRecord - cumulativeRecords;
@@ -4830,6 +4884,7 @@ var FileDatabase = class _FileDatabase {
4830
4884
  throw new FileDatabaseError(`Failed to read file ${file.fileName}: ${error.message}`);
4831
4885
  }
4832
4886
  }
4887
+ this.currentRecord += recordsRead;
4833
4888
  if (result.length > 0) {
4834
4889
  if (nextPage || pageSize !== void 0 && pageSize < this.metadata.totalRecords) {
4835
4890
  this.hasReadFirstPage = true;
@@ -4843,6 +4898,7 @@ var FileDatabase = class _FileDatabase {
4843
4898
  setStartRecord(startRecord) {
4844
4899
  this.currentRecord = startRecord - 1;
4845
4900
  this.hasReadFirstPage = false;
4901
+ this.readFileCache = null;
4846
4902
  }
4847
4903
  /**
4848
4904
  * Reset read pagination state
@@ -4850,6 +4906,7 @@ var FileDatabase = class _FileDatabase {
4850
4906
  resetPagination() {
4851
4907
  this.currentRecord = 0;
4852
4908
  this.hasReadFirstPage = false;
4909
+ this.readFileCache = null;
4853
4910
  }
4854
4911
  /**
4855
4912
  * List filenames in the table directory.