dbnexus 0.1.11 → 0.1.13

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/dist/api.js CHANGED
@@ -1993,10 +1993,10 @@ var require_controller_decorator = __commonJS({
1993
1993
  "node_modules/.pnpm/@nestjs+common@10.4.22_reflect-metadata@0.2.2_rxjs@7.8.2/node_modules/@nestjs/common/decorators/core/controller.decorator.js"(exports2) {
1994
1994
  "use strict";
1995
1995
  Object.defineProperty(exports2, "__esModule", { value: true });
1996
- exports2.Controller = Controller8;
1996
+ exports2.Controller = Controller9;
1997
1997
  var constants_1 = require_constants2();
1998
1998
  var shared_utils_1 = require_shared_utils();
1999
- function Controller8(prefixOrOptions) {
1999
+ function Controller9(prefixOrOptions) {
2000
2000
  const defaultPath = "/";
2001
2001
  const [path4, host, scopeOptions, versionOptions] = (0, shared_utils_1.isUndefined)(prefixOrOptions) ? [defaultPath, void 0, void 0, void 0] : (0, shared_utils_1.isString)(prefixOrOptions) || Array.isArray(prefixOrOptions) ? [prefixOrOptions, void 0, void 0, void 0] : [
2002
2002
  prefixOrOptions.path || defaultPath,
@@ -2416,9 +2416,9 @@ var require_module_decorator = __commonJS({
2416
2416
  "node_modules/.pnpm/@nestjs+common@10.4.22_reflect-metadata@0.2.2_rxjs@7.8.2/node_modules/@nestjs/common/decorators/modules/module.decorator.js"(exports2) {
2417
2417
  "use strict";
2418
2418
  Object.defineProperty(exports2, "__esModule", { value: true });
2419
- exports2.Module = Module10;
2419
+ exports2.Module = Module11;
2420
2420
  var validate_module_keys_util_1 = require_validate_module_keys_util();
2421
- function Module10(metadata) {
2421
+ function Module11(metadata) {
2422
2422
  const propsKeys = Object.keys(metadata);
2423
2423
  (0, validate_module_keys_util_1.validateModuleKeys)(propsKeys);
2424
2424
  return (target) => {
@@ -2539,7 +2539,7 @@ var require_route_params_decorator = __commonJS({
2539
2539
  exports2.assignMetadata = assignMetadata;
2540
2540
  exports2.UploadedFile = UploadedFile;
2541
2541
  exports2.UploadedFiles = UploadedFiles;
2542
- exports2.Query = Query7;
2542
+ exports2.Query = Query8;
2543
2543
  exports2.Body = Body6;
2544
2544
  exports2.RawBody = RawBody;
2545
2545
  exports2.Param = Param6;
@@ -2588,7 +2588,7 @@ var require_route_params_decorator = __commonJS({
2588
2588
  return createPipesRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.FILES)(void 0, ...pipes);
2589
2589
  }
2590
2590
  exports2.Headers = createRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.HEADERS);
2591
- function Query7(property, ...pipes) {
2591
+ function Query8(property, ...pipes) {
2592
2592
  return createPipesRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.QUERY)(property, ...pipes);
2593
2593
  }
2594
2594
  function Body6(property, ...pipes) {
@@ -20438,7 +20438,7 @@ var require_module = __commonJS({
20438
20438
  var constants_2 = require_constants4();
20439
20439
  var instance_wrapper_1 = require_instance_wrapper();
20440
20440
  var module_ref_1 = require_module_ref();
20441
- var Module10 = class {
20441
+ var Module11 = class {
20442
20442
  constructor(_metatype, container) {
20443
20443
  this._metatype = _metatype;
20444
20444
  this.container = container;
@@ -20832,7 +20832,7 @@ var require_module = __commonJS({
20832
20832
  return (0, get_class_scope_1.getClassScope)(provider) === interfaces_1.Scope.TRANSIENT;
20833
20833
  }
20834
20834
  };
20835
- exports2.Module = Module10;
20835
+ exports2.Module = Module11;
20836
20836
  }
20837
20837
  });
20838
20838
 
@@ -57071,7 +57071,7 @@ var require_serve_static_options_interface = __commonJS({
57071
57071
  var require_abstract_loader = __commonJS({
57072
57072
  "node_modules/.pnpm/@nestjs+serve-static@4.0.2_@nestjs+common@10.4.22_reflect-metadata@0.2.2_rxjs@7.8.2__@nestjs+core@10.4.22_express@4.22.1/node_modules/@nestjs/serve-static/dist/loaders/abstract.loader.js"(exports2) {
57073
57073
  "use strict";
57074
- var __decorate25 = exports2 && exports2.__decorate || function(decorators, target, key, desc) {
57074
+ var __decorate27 = exports2 && exports2.__decorate || function(decorators, target, key, desc) {
57075
57075
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
57076
57076
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
57077
57077
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
@@ -57087,7 +57087,7 @@ var require_abstract_loader = __commonJS({
57087
57087
  }
57088
57088
  };
57089
57089
  exports2.AbstractLoader = AbstractLoader;
57090
- exports2.AbstractLoader = AbstractLoader = __decorate25([
57090
+ exports2.AbstractLoader = AbstractLoader = __decorate27([
57091
57091
  (0, common_1.Injectable)()
57092
57092
  ], AbstractLoader);
57093
57093
  }
@@ -57233,7 +57233,7 @@ var require_validate_path_util = __commonJS({
57233
57233
  var require_express_loader = __commonJS({
57234
57234
  "node_modules/.pnpm/@nestjs+serve-static@4.0.2_@nestjs+common@10.4.22_reflect-metadata@0.2.2_rxjs@7.8.2__@nestjs+core@10.4.22_express@4.22.1/node_modules/@nestjs/serve-static/dist/loaders/express.loader.js"(exports2) {
57235
57235
  "use strict";
57236
- var __decorate25 = exports2 && exports2.__decorate || function(decorators, target, key, desc) {
57236
+ var __decorate27 = exports2 && exports2.__decorate || function(decorators, target, key, desc) {
57237
57237
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
57238
57238
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
57239
57239
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
@@ -57279,7 +57279,7 @@ var require_express_loader = __commonJS({
57279
57279
  }
57280
57280
  };
57281
57281
  exports2.ExpressLoader = ExpressLoader;
57282
- exports2.ExpressLoader = ExpressLoader = __decorate25([
57282
+ exports2.ExpressLoader = ExpressLoader = __decorate27([
57283
57283
  (0, common_1.Injectable)()
57284
57284
  ], ExpressLoader);
57285
57285
  }
@@ -57289,7 +57289,7 @@ var require_express_loader = __commonJS({
57289
57289
  var require_fastify_loader = __commonJS({
57290
57290
  "node_modules/.pnpm/@nestjs+serve-static@4.0.2_@nestjs+common@10.4.22_reflect-metadata@0.2.2_rxjs@7.8.2__@nestjs+core@10.4.22_express@4.22.1/node_modules/@nestjs/serve-static/dist/loaders/fastify.loader.js"(exports2) {
57291
57291
  "use strict";
57292
- var __decorate25 = exports2 && exports2.__decorate || function(decorators, target, key, desc) {
57292
+ var __decorate27 = exports2 && exports2.__decorate || function(decorators, target, key, desc) {
57293
57293
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
57294
57294
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
57295
57295
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
@@ -57342,7 +57342,7 @@ var require_fastify_loader = __commonJS({
57342
57342
  }
57343
57343
  };
57344
57344
  exports2.FastifyLoader = FastifyLoader;
57345
- exports2.FastifyLoader = FastifyLoader = __decorate25([
57345
+ exports2.FastifyLoader = FastifyLoader = __decorate27([
57346
57346
  (0, common_1.Injectable)()
57347
57347
  ], FastifyLoader);
57348
57348
  }
@@ -57352,7 +57352,7 @@ var require_fastify_loader = __commonJS({
57352
57352
  var require_noop_loader = __commonJS({
57353
57353
  "node_modules/.pnpm/@nestjs+serve-static@4.0.2_@nestjs+common@10.4.22_reflect-metadata@0.2.2_rxjs@7.8.2__@nestjs+core@10.4.22_express@4.22.1/node_modules/@nestjs/serve-static/dist/loaders/noop.loader.js"(exports2) {
57354
57354
  "use strict";
57355
- var __decorate25 = exports2 && exports2.__decorate || function(decorators, target, key, desc) {
57355
+ var __decorate27 = exports2 && exports2.__decorate || function(decorators, target, key, desc) {
57356
57356
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
57357
57357
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
57358
57358
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
@@ -57367,7 +57367,7 @@ var require_noop_loader = __commonJS({
57367
57367
  }
57368
57368
  };
57369
57369
  exports2.NoopLoader = NoopLoader;
57370
- exports2.NoopLoader = NoopLoader = __decorate25([
57370
+ exports2.NoopLoader = NoopLoader = __decorate27([
57371
57371
  (0, common_1.Injectable)()
57372
57372
  ], NoopLoader);
57373
57373
  }
@@ -57407,16 +57407,16 @@ var require_serve_static_providers = __commonJS({
57407
57407
  var require_serve_static_module = __commonJS({
57408
57408
  "node_modules/.pnpm/@nestjs+serve-static@4.0.2_@nestjs+common@10.4.22_reflect-metadata@0.2.2_rxjs@7.8.2__@nestjs+core@10.4.22_express@4.22.1/node_modules/@nestjs/serve-static/dist/serve-static.module.js"(exports2) {
57409
57409
  "use strict";
57410
- var __decorate25 = exports2 && exports2.__decorate || function(decorators, target, key, desc) {
57410
+ var __decorate27 = exports2 && exports2.__decorate || function(decorators, target, key, desc) {
57411
57411
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
57412
57412
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
57413
57413
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
57414
57414
  return c > 3 && r && Object.defineProperty(target, key, r), r;
57415
57415
  };
57416
- var __metadata14 = exports2 && exports2.__metadata || function(k, v) {
57416
+ var __metadata15 = exports2 && exports2.__metadata || function(k, v) {
57417
57417
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
57418
57418
  };
57419
- var __param8 = exports2 && exports2.__param || function(paramIndex, decorator) {
57419
+ var __param9 = exports2 && exports2.__param || function(paramIndex, decorator) {
57420
57420
  return function(target, key) {
57421
57421
  decorator(target, key, paramIndex);
57422
57422
  };
@@ -57489,12 +57489,12 @@ var require_serve_static_module = __commonJS({
57489
57489
  }
57490
57490
  };
57491
57491
  exports2.ServeStaticModule = ServeStaticModule2;
57492
- exports2.ServeStaticModule = ServeStaticModule2 = ServeStaticModule_1 = __decorate25([
57492
+ exports2.ServeStaticModule = ServeStaticModule2 = ServeStaticModule_1 = __decorate27([
57493
57493
  (0, common_1.Module)({
57494
57494
  providers: [...serve_static_providers_1.serveStaticProviders]
57495
57495
  }),
57496
- __param8(0, (0, common_1.Inject)(serve_static_constants_1.SERVE_STATIC_MODULE_OPTIONS)),
57497
- __metadata14("design:paramtypes", [
57496
+ __param9(0, (0, common_1.Inject)(serve_static_constants_1.SERVE_STATIC_MODULE_OPTIONS)),
57497
+ __metadata15("design:paramtypes", [
57498
57498
  Array,
57499
57499
  abstract_loader_1.AbstractLoader,
57500
57500
  core_1.HttpAdapterHost
@@ -59520,7 +59520,7 @@ var require_query2 = __commonJS({
59520
59520
  var { EventEmitter } = __require("events");
59521
59521
  var Result2 = require_result();
59522
59522
  var utils = require_utils10();
59523
- var Query7 = class extends EventEmitter {
59523
+ var Query8 = class extends EventEmitter {
59524
59524
  constructor(config, values, callback) {
59525
59525
  super();
59526
59526
  config = utils.normalizeQueryConfig(config, values, callback);
@@ -59706,7 +59706,7 @@ var require_query2 = __commonJS({
59706
59706
  handleCopyData(msg, connection) {
59707
59707
  }
59708
59708
  };
59709
- module2.exports = Query7;
59709
+ module2.exports = Query8;
59710
59710
  }
59711
59711
  });
59712
59712
 
@@ -61111,7 +61111,7 @@ var require_client = __commonJS({
61111
61111
  var sasl = require_sasl();
61112
61112
  var TypeOverrides2 = require_type_overrides();
61113
61113
  var ConnectionParameters = require_connection_parameters();
61114
- var Query7 = require_query2();
61114
+ var Query8 = require_query2();
61115
61115
  var defaults2 = require_defaults();
61116
61116
  var Connection2 = require_connection();
61117
61117
  var crypto3 = require_utils11();
@@ -61542,7 +61542,7 @@ var require_client = __commonJS({
61542
61542
  }
61543
61543
  } else {
61544
61544
  readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
61545
- query = new Query7(config, values, callback);
61545
+ query = new Query8(config, values, callback);
61546
61546
  if (!query.callback) {
61547
61547
  result = new this._Promise((resolve, reject) => {
61548
61548
  query.callback = (err, res) => err ? reject(err) : resolve(res);
@@ -61624,7 +61624,7 @@ var require_client = __commonJS({
61624
61624
  }
61625
61625
  }
61626
61626
  };
61627
- Client2.Query = Query7;
61627
+ Client2.Query = Query8;
61628
61628
  module2.exports = Client2;
61629
61629
  }
61630
61630
  });
@@ -74578,7 +74578,7 @@ var require_query4 = __commonJS({
74578
74578
  var CommandCode = require_commands();
74579
74579
  var StringParser = require_string();
74580
74580
  var CharsetToEncoding = require_charset_encodings();
74581
- var Query7 = class {
74581
+ var Query8 = class {
74582
74582
  constructor(sql, charsetNumber) {
74583
74583
  this.query = sql;
74584
74584
  this.charsetNumber = charsetNumber;
@@ -74595,7 +74595,7 @@ var require_query4 = __commonJS({
74595
74595
  return packet;
74596
74596
  }
74597
74597
  };
74598
- module2.exports = Query7;
74598
+ module2.exports = Query8;
74599
74599
  }
74600
74600
  });
74601
74601
 
@@ -74930,7 +74930,7 @@ var require_packets = __commonJS({
74930
74930
  var HandshakeResponse = require_handshake_response();
74931
74931
  var PrepareStatement = require_prepare_statement();
74932
74932
  var PreparedStatementHeader = require_prepared_statement_header();
74933
- var Query7 = require_query4();
74933
+ var Query8 = require_query4();
74934
74934
  var RegisterSlave = require_register_slave();
74935
74935
  var ResultSetHeader = require_resultset_header();
74936
74936
  var SSLRequest = require_ssl_request();
@@ -74950,7 +74950,7 @@ var require_packets = __commonJS({
74950
74950
  HandshakeResponse,
74951
74951
  PrepareStatement,
74952
74952
  PreparedStatementHeader,
74953
- Query: Query7,
74953
+ Query: Query8,
74954
74954
  RegisterSlave,
74955
74955
  ResultSetHeader,
74956
74956
  SSLRequest,
@@ -76825,7 +76825,7 @@ var require_query5 = __commonJS({
76825
76825
  var staticParser = require_static_text_parser();
76826
76826
  var ServerStatus = require_server_status();
76827
76827
  var EmptyPacket = new Packets.Packet(0, Buffer.allocUnsafe(4), 0, 4);
76828
- var Query7 = class _Query extends Command {
76828
+ var Query8 = class _Query extends Command {
76829
76829
  constructor(options, callback) {
76830
76830
  super();
76831
76831
  this.sql = options.sql;
@@ -77125,8 +77125,8 @@ var require_query5 = __commonJS({
77125
77125
  }
77126
77126
  }
77127
77127
  };
77128
- Query7.prototype.catch = Query7.prototype.then;
77129
- module2.exports = Query7;
77128
+ Query8.prototype.catch = Query8.prototype.then;
77129
+ module2.exports = Query8;
77130
77130
  }
77131
77131
  });
77132
77132
 
@@ -77520,7 +77520,7 @@ var require_execute2 = __commonJS({
77520
77520
  "node_modules/.pnpm/mysql2@3.16.0/node_modules/mysql2/lib/commands/execute.js"(exports2, module2) {
77521
77521
  "use strict";
77522
77522
  var Command = require_command();
77523
- var Query7 = require_query5();
77523
+ var Query8 = require_query5();
77524
77524
  var Packets = require_packets();
77525
77525
  var getBinaryParser = require_binary_parser();
77526
77526
  var getStaticBinaryParser = require_static_binary_parser();
@@ -77597,15 +77597,15 @@ var require_execute2 = __commonJS({
77597
77597
  return _Execute.prototype.row;
77598
77598
  }
77599
77599
  };
77600
- Execute.prototype.done = Query7.prototype.done;
77601
- Execute.prototype.doneInsert = Query7.prototype.doneInsert;
77602
- Execute.prototype.resultsetHeader = Query7.prototype.resultsetHeader;
77603
- Execute.prototype._findOrCreateReadStream = Query7.prototype._findOrCreateReadStream;
77604
- Execute.prototype._streamLocalInfile = Query7.prototype._streamLocalInfile;
77605
- Execute.prototype._setTimeout = Query7.prototype._setTimeout;
77606
- Execute.prototype._handleTimeoutError = Query7.prototype._handleTimeoutError;
77607
- Execute.prototype.row = Query7.prototype.row;
77608
- Execute.prototype.stream = Query7.prototype.stream;
77600
+ Execute.prototype.done = Query8.prototype.done;
77601
+ Execute.prototype.doneInsert = Query8.prototype.doneInsert;
77602
+ Execute.prototype.resultsetHeader = Query8.prototype.resultsetHeader;
77603
+ Execute.prototype._findOrCreateReadStream = Query8.prototype._findOrCreateReadStream;
77604
+ Execute.prototype._streamLocalInfile = Query8.prototype._streamLocalInfile;
77605
+ Execute.prototype._setTimeout = Query8.prototype._setTimeout;
77606
+ Execute.prototype._handleTimeoutError = Query8.prototype._handleTimeoutError;
77607
+ Execute.prototype.row = Query8.prototype.row;
77608
+ Execute.prototype.stream = Query8.prototype.stream;
77609
77609
  module2.exports = Execute;
77610
77610
  }
77611
77611
  });
@@ -78104,7 +78104,7 @@ var require_commands2 = __commonJS({
78104
78104
  "use strict";
78105
78105
  var ClientHandshake = require_client_handshake();
78106
78106
  var ServerHandshake = require_server_handshake();
78107
- var Query7 = require_query5();
78107
+ var Query8 = require_query5();
78108
78108
  var Prepare = require_prepare();
78109
78109
  var CloseStatement = require_close_statement2();
78110
78110
  var Execute = require_execute2();
@@ -78116,7 +78116,7 @@ var require_commands2 = __commonJS({
78116
78116
  module2.exports = {
78117
78117
  ClientHandshake,
78118
78118
  ServerHandshake,
78119
- Query: Query7,
78119
+ Query: Query8,
78120
78120
  Prepare,
78121
78121
  CloseStatement,
78122
78122
  Execute,
@@ -80928,10 +80928,10 @@ var require_promise = __commonJS({
80928
80928
  // apps/api/dist/main.js
80929
80929
  var import_reflect_metadata = __toESM(require_Reflect(), 1);
80930
80930
  var import_core = __toESM(require_core2(), 1);
80931
- var import_common24 = __toESM(require_common(), 1);
80931
+ var import_common26 = __toESM(require_common(), 1);
80932
80932
 
80933
80933
  // apps/api/dist/app.module.js
80934
- var import_common23 = __toESM(require_common(), 1);
80934
+ var import_common25 = __toESM(require_common(), 1);
80935
80935
  var import_serve_static = __toESM(require_serve_static2(), 1);
80936
80936
  import { join as join3 } from "path";
80937
80937
  import { fileURLToPath } from "url";
@@ -80952,7 +80952,7 @@ var import_common = __toESM(require_common(), 1);
80952
80952
  import Database from "better-sqlite3";
80953
80953
 
80954
80954
  // packages/metadata/dist/schema.js
80955
- var SCHEMA_VERSION = 9;
80955
+ var SCHEMA_VERSION = 13;
80956
80956
  var MIGRATIONS = [
80957
80957
  // Version 1: Initial schema
80958
80958
  `
@@ -81169,6 +81169,85 @@ var MIGRATIONS = [
81169
81169
  ALTER TABLE connections ADD COLUMN connection_type TEXT NOT NULL DEFAULT 'local' CHECK(connection_type IN ('local', 'docker', 'remote'));
81170
81170
 
81171
81171
  UPDATE schema_version SET version = 9;
81172
+ `,
81173
+ // Version 10: Refactor sync_runs to work without sync_configs (add direct connection/table info)
81174
+ `
81175
+ -- Create new sync_runs table without FK constraint
81176
+ CREATE TABLE IF NOT EXISTS sync_runs_new (
81177
+ id TEXT PRIMARY KEY,
81178
+ source_connection_id TEXT,
81179
+ target_connection_id TEXT,
81180
+ schema_name TEXT,
81181
+ table_name TEXT,
81182
+ group_id TEXT,
81183
+ started_at TEXT NOT NULL DEFAULT (datetime('now')),
81184
+ completed_at TEXT,
81185
+ status TEXT NOT NULL DEFAULT 'running',
81186
+ inserts INTEGER NOT NULL DEFAULT 0,
81187
+ updates INTEGER NOT NULL DEFAULT 0,
81188
+ deletes INTEGER NOT NULL DEFAULT 0,
81189
+ errors_json TEXT,
81190
+ FOREIGN KEY (source_connection_id) REFERENCES connections(id) ON DELETE SET NULL,
81191
+ FOREIGN KEY (target_connection_id) REFERENCES connections(id) ON DELETE SET NULL,
81192
+ FOREIGN KEY (group_id) REFERENCES database_groups(id) ON DELETE SET NULL
81193
+ );
81194
+
81195
+ -- Copy existing data (old sync_config_id will be lost, but that's ok)
81196
+ INSERT INTO sync_runs_new (id, started_at, completed_at, status, inserts, updates, deletes, errors_json)
81197
+ SELECT id, started_at, completed_at, status, inserts, updates, deletes, errors_json FROM sync_runs;
81198
+
81199
+ -- Drop old table and rename
81200
+ DROP TABLE sync_runs;
81201
+ ALTER TABLE sync_runs_new RENAME TO sync_runs;
81202
+
81203
+ -- Create indexes
81204
+ CREATE INDEX IF NOT EXISTS idx_sync_runs_source ON sync_runs(source_connection_id);
81205
+ CREATE INDEX IF NOT EXISTS idx_sync_runs_target ON sync_runs(target_connection_id);
81206
+ CREATE INDEX IF NOT EXISTS idx_sync_runs_group ON sync_runs(group_id);
81207
+ CREATE INDEX IF NOT EXISTS idx_sync_runs_started ON sync_runs(started_at DESC);
81208
+
81209
+ UPDATE schema_version SET version = 10;
81210
+ `,
81211
+ // Version 11: Add sql_statements to sync_runs for tracking executed SQL
81212
+ `
81213
+ ALTER TABLE sync_runs ADD COLUMN sql_statements TEXT;
81214
+
81215
+ UPDATE schema_version SET version = 11;
81216
+ `,
81217
+ // Version 12: Add group_id to migration_history for tracking group-based migrations
81218
+ `
81219
+ ALTER TABLE migration_history ADD COLUMN group_id TEXT REFERENCES database_groups(id) ON DELETE SET NULL;
81220
+
81221
+ UPDATE schema_version SET version = 12;
81222
+ `,
81223
+ // Version 13: Rename tables and indexes for consistency (*_history -> *_logs)
81224
+ `
81225
+ -- Rename query_history to query_logs
81226
+ ALTER TABLE query_history RENAME TO query_logs;
81227
+ DROP INDEX IF EXISTS idx_query_history_connection;
81228
+ DROP INDEX IF EXISTS idx_query_history_executed_at;
81229
+ CREATE INDEX IF NOT EXISTS idx_query_logs_connection ON query_logs(connection_id);
81230
+ CREATE INDEX IF NOT EXISTS idx_query_logs_executed_at ON query_logs(executed_at DESC);
81231
+
81232
+ -- Rename migration_history to migration_logs
81233
+ ALTER TABLE migration_history RENAME TO migration_logs;
81234
+ DROP INDEX IF EXISTS idx_migration_history_applied_at;
81235
+ DROP INDEX IF EXISTS idx_migration_history_target;
81236
+ CREATE INDEX IF NOT EXISTS idx_migration_logs_applied_at ON migration_logs(applied_at DESC);
81237
+ CREATE INDEX IF NOT EXISTS idx_migration_logs_target ON migration_logs(target_connection_id);
81238
+
81239
+ -- Rename sync_runs to sync_run_logs
81240
+ ALTER TABLE sync_runs RENAME TO sync_run_logs;
81241
+ DROP INDEX IF EXISTS idx_sync_runs_source;
81242
+ DROP INDEX IF EXISTS idx_sync_runs_target;
81243
+ DROP INDEX IF EXISTS idx_sync_runs_group;
81244
+ DROP INDEX IF EXISTS idx_sync_runs_started;
81245
+ CREATE INDEX IF NOT EXISTS idx_sync_run_logs_source ON sync_run_logs(source_connection_id);
81246
+ CREATE INDEX IF NOT EXISTS idx_sync_run_logs_target ON sync_run_logs(target_connection_id);
81247
+ CREATE INDEX IF NOT EXISTS idx_sync_run_logs_group ON sync_run_logs(group_id);
81248
+ CREATE INDEX IF NOT EXISTS idx_sync_run_logs_started ON sync_run_logs(started_at DESC);
81249
+
81250
+ UPDATE schema_version SET version = 13;
81172
81251
  `
81173
81252
  ];
81174
81253
 
@@ -81184,10 +81263,12 @@ var MetadataDatabase = class {
81184
81263
  * Initialize the database schema
81185
81264
  */
81186
81265
  initialize() {
81187
- const currentVersion = this.getSchemaVersion();
81266
+ let currentVersion = this.getSchemaVersion();
81188
81267
  if (currentVersion === 0) {
81189
81268
  this.db.exec(MIGRATIONS[0]);
81190
- } else if (currentVersion < SCHEMA_VERSION) {
81269
+ currentVersion = this.getSchemaVersion();
81270
+ }
81271
+ if (currentVersion < SCHEMA_VERSION) {
81191
81272
  for (let i = currentVersion; i < SCHEMA_VERSION; i++) {
81192
81273
  const migration = MIGRATIONS[i];
81193
81274
  if (migration) {
@@ -81470,11 +81551,24 @@ var ConnectionRepository = class {
81470
81551
  return this.findById(id);
81471
81552
  }
81472
81553
  /**
81473
- * Delete a connection
81554
+ * Delete a connection and all related data
81474
81555
  */
81475
81556
  delete(id) {
81476
- const result = this.db.prepare("DELETE FROM connections WHERE id = ?").run(id);
81477
- return result.changes > 0;
81557
+ this.db.prepare("PRAGMA foreign_keys = OFF").run();
81558
+ try {
81559
+ this.db.prepare("DELETE FROM query_history WHERE connection_id = ?").run(id);
81560
+ this.db.prepare("DELETE FROM schema_snapshots WHERE connection_id = ?").run(id);
81561
+ this.db.prepare("DELETE FROM migration_history WHERE source_connection_id = ? OR target_connection_id = ?").run(id, id);
81562
+ this.db.prepare("DELETE FROM sync_configs WHERE source_connection_id = ? OR target_connection_id = ?").run(id, id);
81563
+ this.db.prepare("DELETE FROM sync_runs WHERE source_connection_id = ? OR target_connection_id = ?").run(id, id);
81564
+ this.db.prepare("UPDATE saved_queries SET connection_id = NULL WHERE connection_id = ?").run(id);
81565
+ this.db.prepare("UPDATE database_groups SET source_connection_id = NULL WHERE source_connection_id = ?").run(id);
81566
+ this.db.prepare("UPDATE connections SET group_id = NULL WHERE group_id IN (SELECT id FROM database_groups WHERE source_connection_id = ?)").run(id);
81567
+ const result = this.db.prepare("DELETE FROM connections WHERE id = ?").run(id);
81568
+ return result.changes > 0;
81569
+ } finally {
81570
+ this.db.prepare("PRAGMA foreign_keys = ON").run();
81571
+ }
81478
81572
  }
81479
81573
  /**
81480
81574
  * Get the decrypted password for a connection
@@ -81524,7 +81618,7 @@ var ConnectionRepository = class {
81524
81618
  };
81525
81619
 
81526
81620
  // packages/metadata/dist/repositories/query.repository.js
81527
- var QueryRepository = class {
81621
+ var QueryLogsRepository = class {
81528
81622
  db;
81529
81623
  constructor(metadataDb) {
81530
81624
  this.db = metadataDb.getDb();
@@ -81609,22 +81703,22 @@ var QueryRepository = class {
81609
81703
  const id = MetadataDatabase.generateId();
81610
81704
  const now = (/* @__PURE__ */ new Date()).toISOString();
81611
81705
  this.db.prepare(`
81612
- INSERT INTO query_history (id, connection_id, sql, executed_at, execution_time_ms, row_count, success, error)
81706
+ INSERT INTO query_logs (id, connection_id, sql, executed_at, execution_time_ms, row_count, success, error)
81613
81707
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
81614
81708
  `).run(id, input.connectionId, input.sql, now, input.executionTimeMs, input.rowCount, input.success ? 1 : 0, input.error ?? null);
81615
81709
  return this.findHistoryEntryById(id);
81616
81710
  }
81617
81711
  findHistoryEntryById(id) {
81618
- const row = this.db.prepare("SELECT * FROM query_history WHERE id = ?").get(id);
81712
+ const row = this.db.prepare("SELECT * FROM query_logs WHERE id = ?").get(id);
81619
81713
  return row ? this.rowToHistoryEntry(row) : null;
81620
81714
  }
81621
81715
  findRecentHistory(limit = 100, connectionId) {
81622
- const query = connectionId ? "SELECT * FROM query_history WHERE connection_id = ? ORDER BY executed_at DESC LIMIT ?" : "SELECT * FROM query_history ORDER BY executed_at DESC LIMIT ?";
81716
+ const query = connectionId ? "SELECT * FROM query_logs WHERE connection_id = ? ORDER BY executed_at DESC LIMIT ?" : "SELECT * FROM query_logs ORDER BY executed_at DESC LIMIT ?";
81623
81717
  const rows = this.db.prepare(query).all(...connectionId ? [connectionId, limit] : [limit]);
81624
81718
  return rows.map((row) => this.rowToHistoryEntry(row));
81625
81719
  }
81626
81720
  clearHistory(connectionId) {
81627
- const query = connectionId ? "DELETE FROM query_history WHERE connection_id = ?" : "DELETE FROM query_history";
81721
+ const query = connectionId ? "DELETE FROM query_logs WHERE connection_id = ?" : "DELETE FROM query_logs";
81628
81722
  const result = connectionId ? this.db.prepare(query).run(connectionId) : this.db.prepare(query).run();
81629
81723
  return result.changes;
81630
81724
  }
@@ -81662,8 +81756,8 @@ var QueryRepository = class {
81662
81756
  }
81663
81757
  };
81664
81758
 
81665
- // packages/metadata/dist/repositories/migration-history.repository.js
81666
- var MigrationHistoryRepository = class {
81759
+ // packages/metadata/dist/repositories/migration-logs.repository.js
81760
+ var MigrationLogsRepository = class {
81667
81761
  db;
81668
81762
  constructor(db) {
81669
81763
  this.db = db;
@@ -81674,15 +81768,25 @@ var MigrationHistoryRepository = class {
81674
81768
  create(input) {
81675
81769
  const id = crypto.randomUUID();
81676
81770
  const sqlJson = JSON.stringify(input.sqlStatements);
81677
- this.db.getDb().prepare(`
81678
- INSERT INTO migration_history (
81679
- id, source_connection_id, target_connection_id,
81680
- source_schema, target_schema, description,
81681
- sql_statements, success, error
81682
- )
81683
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
81684
- `).run(id, input.sourceConnectionId, input.targetConnectionId, input.sourceSchema, input.targetSchema, input.description || null, sqlJson, input.success ? 1 : 0, input.error || null);
81685
- return this.findById(id);
81771
+ const fkWasEnabled = this.db.getDb().prepare("PRAGMA foreign_keys").get();
81772
+ if (fkWasEnabled.foreign_keys) {
81773
+ this.db.getDb().prepare("PRAGMA foreign_keys = OFF").run();
81774
+ }
81775
+ try {
81776
+ this.db.getDb().prepare(`
81777
+ INSERT INTO migration_logs (
81778
+ id, source_connection_id, target_connection_id,
81779
+ source_schema, target_schema, group_id, description,
81780
+ sql_statements, success, error
81781
+ )
81782
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
81783
+ `).run(id, input.sourceConnectionId, input.targetConnectionId, input.sourceSchema, input.targetSchema, input.groupId || null, input.description || null, sqlJson, input.success ? 1 : 0, input.error || null);
81784
+ return this.findById(id);
81785
+ } finally {
81786
+ if (fkWasEnabled.foreign_keys) {
81787
+ this.db.getDb().prepare("PRAGMA foreign_keys = ON").run();
81788
+ }
81789
+ }
81686
81790
  }
81687
81791
  /**
81688
81792
  * Find a migration by ID
@@ -81692,10 +81796,12 @@ var MigrationHistoryRepository = class {
81692
81796
  SELECT
81693
81797
  mh.*,
81694
81798
  sc.name as source_connection_name,
81695
- tc.name as target_connection_name
81696
- FROM migration_history mh
81799
+ tc.name as target_connection_name,
81800
+ ig.name as group_name
81801
+ FROM migration_logs mh
81697
81802
  LEFT JOIN connections sc ON mh.source_connection_id = sc.id
81698
81803
  LEFT JOIN connections tc ON mh.target_connection_id = tc.id
81804
+ LEFT JOIN database_groups ig ON mh.group_id = ig.id
81699
81805
  WHERE mh.id = ?
81700
81806
  `).get(id);
81701
81807
  return row ? this.rowToEntry(row) : null;
@@ -81708,10 +81814,12 @@ var MigrationHistoryRepository = class {
81708
81814
  SELECT
81709
81815
  mh.*,
81710
81816
  sc.name as source_connection_name,
81711
- tc.name as target_connection_name
81712
- FROM migration_history mh
81817
+ tc.name as target_connection_name,
81818
+ ig.name as group_name
81819
+ FROM migration_logs mh
81713
81820
  LEFT JOIN connections sc ON mh.source_connection_id = sc.id
81714
81821
  LEFT JOIN connections tc ON mh.target_connection_id = tc.id
81822
+ LEFT JOIN database_groups ig ON mh.group_id = ig.id
81715
81823
  `;
81716
81824
  const params = [];
81717
81825
  if (options?.targetConnectionId) {
@@ -81730,13 +81838,23 @@ var MigrationHistoryRepository = class {
81730
81838
  * Delete a migration record
81731
81839
  */
81732
81840
  delete(id) {
81733
- const result = this.db.getDb().prepare(`
81734
- DELETE FROM migration_history WHERE id = ?
81735
- `).run(id);
81736
- return result.changes > 0;
81841
+ const fkWasEnabled = this.db.getDb().prepare("PRAGMA foreign_keys").get();
81842
+ if (fkWasEnabled.foreign_keys) {
81843
+ this.db.getDb().prepare("PRAGMA foreign_keys = OFF").run();
81844
+ }
81845
+ try {
81846
+ const result = this.db.getDb().prepare(`
81847
+ DELETE FROM migration_logs WHERE id = ?
81848
+ `).run(id);
81849
+ return result.changes > 0;
81850
+ } finally {
81851
+ if (fkWasEnabled.foreign_keys) {
81852
+ this.db.getDb().prepare("PRAGMA foreign_keys = ON").run();
81853
+ }
81854
+ }
81737
81855
  }
81738
81856
  /**
81739
- * Convert database row to MigrationHistoryEntry
81857
+ * Convert database row to MigrationLogEntry
81740
81858
  */
81741
81859
  rowToEntry(row) {
81742
81860
  return {
@@ -81745,13 +81863,15 @@ var MigrationHistoryRepository = class {
81745
81863
  targetConnectionId: row.target_connection_id,
81746
81864
  sourceSchema: row.source_schema,
81747
81865
  targetSchema: row.target_schema,
81866
+ groupId: row.group_id || void 0,
81748
81867
  description: row.description || void 0,
81749
81868
  sqlStatements: JSON.parse(row.sql_statements),
81750
81869
  appliedAt: row.applied_at,
81751
81870
  success: row.success === 1,
81752
81871
  error: row.error || void 0,
81753
81872
  sourceConnectionName: row.source_connection_name,
81754
- targetConnectionName: row.target_connection_name
81873
+ targetConnectionName: row.target_connection_name,
81874
+ groupName: row.group_name || void 0
81755
81875
  };
81756
81876
  }
81757
81877
  };
@@ -81986,6 +82106,558 @@ var DatabaseGroupRepository = class {
81986
82106
  }
81987
82107
  };
81988
82108
 
82109
+ // packages/metadata/dist/repositories/sync-run-logs.repository.js
82110
+ var SyncRunLogsRepository = class {
82111
+ db;
82112
+ constructor(db) {
82113
+ this.db = db;
82114
+ }
82115
+ /**
82116
+ * Create a new sync run (starts in 'running' status)
82117
+ */
82118
+ create(input) {
82119
+ const id = crypto.randomUUID();
82120
+ this.db.getDb().prepare(`
82121
+ INSERT INTO sync_run_logs (id, source_connection_id, target_connection_id, schema_name, table_name, group_id, status)
82122
+ VALUES (?, ?, ?, ?, ?, ?, 'running')
82123
+ `).run(id, input.sourceConnectionId, input.targetConnectionId, input.schemaName || null, input.tableName || null, input.groupId || null);
82124
+ return this.findById(id);
82125
+ }
82126
+ /**
82127
+ * Find a sync run by ID
82128
+ */
82129
+ findById(id) {
82130
+ const row = this.db.getDb().prepare(`
82131
+ SELECT
82132
+ sr.*,
82133
+ src.name as source_connection_name,
82134
+ tgt.name as target_connection_name,
82135
+ dg.name as group_name
82136
+ FROM sync_run_logs sr
82137
+ LEFT JOIN connections src ON sr.source_connection_id = src.id
82138
+ LEFT JOIN connections tgt ON sr.target_connection_id = tgt.id
82139
+ LEFT JOIN database_groups dg ON sr.group_id = dg.id
82140
+ WHERE sr.id = ?
82141
+ `).get(id);
82142
+ return row ? this.rowToRun(row) : null;
82143
+ }
82144
+ /**
82145
+ * Find sync runs by group ID
82146
+ */
82147
+ findByGroupId(groupId, limit) {
82148
+ let query = `
82149
+ SELECT
82150
+ sr.*,
82151
+ src.name as source_connection_name,
82152
+ tgt.name as target_connection_name,
82153
+ dg.name as group_name
82154
+ FROM sync_run_logs sr
82155
+ LEFT JOIN connections src ON sr.source_connection_id = src.id
82156
+ LEFT JOIN connections tgt ON sr.target_connection_id = tgt.id
82157
+ LEFT JOIN database_groups dg ON sr.group_id = dg.id
82158
+ WHERE sr.group_id = ?
82159
+ ORDER BY sr.started_at DESC
82160
+ `;
82161
+ if (limit) {
82162
+ query += ` LIMIT ${limit}`;
82163
+ }
82164
+ const rows = this.db.getDb().prepare(query).all(groupId);
82165
+ return rows.map((row) => this.rowToRun(row));
82166
+ }
82167
+ /**
82168
+ * Find sync runs by connection ID (either source or target)
82169
+ */
82170
+ findByConnectionId(connectionId, limit) {
82171
+ let query = `
82172
+ SELECT
82173
+ sr.*,
82174
+ src.name as source_connection_name,
82175
+ tgt.name as target_connection_name,
82176
+ dg.name as group_name
82177
+ FROM sync_run_logs sr
82178
+ LEFT JOIN connections src ON sr.source_connection_id = src.id
82179
+ LEFT JOIN connections tgt ON sr.target_connection_id = tgt.id
82180
+ LEFT JOIN database_groups dg ON sr.group_id = dg.id
82181
+ WHERE sr.source_connection_id = ? OR sr.target_connection_id = ?
82182
+ ORDER BY sr.started_at DESC
82183
+ `;
82184
+ if (limit) {
82185
+ query += ` LIMIT ${limit}`;
82186
+ }
82187
+ const rows = this.db.getDb().prepare(query).all(connectionId, connectionId);
82188
+ return rows.map((row) => this.rowToRun(row));
82189
+ }
82190
+ /**
82191
+ * Find recent sync runs
82192
+ */
82193
+ findRecent(limit = 50) {
82194
+ const rows = this.db.getDb().prepare(`
82195
+ SELECT
82196
+ sr.*,
82197
+ src.name as source_connection_name,
82198
+ tgt.name as target_connection_name,
82199
+ dg.name as group_name
82200
+ FROM sync_run_logs sr
82201
+ LEFT JOIN connections src ON sr.source_connection_id = src.id
82202
+ LEFT JOIN connections tgt ON sr.target_connection_id = tgt.id
82203
+ LEFT JOIN database_groups dg ON sr.group_id = dg.id
82204
+ ORDER BY sr.started_at DESC
82205
+ LIMIT ?
82206
+ `).all(limit);
82207
+ return rows.map((row) => this.rowToRun(row));
82208
+ }
82209
+ /**
82210
+ * Find running sync runs
82211
+ */
82212
+ findRunning() {
82213
+ const rows = this.db.getDb().prepare(`
82214
+ SELECT
82215
+ sr.*,
82216
+ src.name as source_connection_name,
82217
+ tgt.name as target_connection_name,
82218
+ dg.name as group_name
82219
+ FROM sync_run_logs sr
82220
+ LEFT JOIN connections src ON sr.source_connection_id = src.id
82221
+ LEFT JOIN connections tgt ON sr.target_connection_id = tgt.id
82222
+ LEFT JOIN database_groups dg ON sr.group_id = dg.id
82223
+ WHERE sr.status = 'running'
82224
+ ORDER BY sr.started_at DESC
82225
+ `).all();
82226
+ return rows.map((row) => this.rowToRun(row));
82227
+ }
82228
+ /**
82229
+ * Update a sync run
82230
+ */
82231
+ update(id, input) {
82232
+ const updates = [];
82233
+ const params = [];
82234
+ if (input.status !== void 0) {
82235
+ updates.push("status = ?");
82236
+ params.push(input.status);
82237
+ if (["completed", "failed", "cancelled"].includes(input.status)) {
82238
+ updates.push("completed_at = datetime('now')");
82239
+ }
82240
+ }
82241
+ if (input.inserts !== void 0) {
82242
+ updates.push("inserts = ?");
82243
+ params.push(input.inserts);
82244
+ }
82245
+ if (input.updates !== void 0) {
82246
+ updates.push("updates = ?");
82247
+ params.push(input.updates);
82248
+ }
82249
+ if (input.deletes !== void 0) {
82250
+ updates.push("deletes = ?");
82251
+ params.push(input.deletes);
82252
+ }
82253
+ if (input.errors !== void 0) {
82254
+ updates.push("errors_json = ?");
82255
+ params.push(JSON.stringify(input.errors));
82256
+ }
82257
+ if (input.sqlStatements !== void 0) {
82258
+ updates.push("sql_statements = ?");
82259
+ params.push(JSON.stringify(input.sqlStatements));
82260
+ }
82261
+ if (updates.length === 0) {
82262
+ return this.findById(id);
82263
+ }
82264
+ params.push(id);
82265
+ this.db.getDb().prepare(`UPDATE sync_run_logs SET ${updates.join(", ")} WHERE id = ?`).run(...params);
82266
+ return this.findById(id);
82267
+ }
82268
+ /**
82269
+ * Complete a sync run with results
82270
+ */
82271
+ complete(id, results) {
82272
+ return this.update(id, {
82273
+ status: results.errors.length > 0 ? "failed" : "completed",
82274
+ inserts: results.inserts,
82275
+ updates: results.updates,
82276
+ deletes: results.deletes,
82277
+ errors: results.errors
82278
+ });
82279
+ }
82280
+ /**
82281
+ * Delete a sync run
82282
+ */
82283
+ delete(id) {
82284
+ const result = this.db.getDb().prepare("DELETE FROM sync_run_logs WHERE id = ?").run(id);
82285
+ return result.changes > 0;
82286
+ }
82287
+ /**
82288
+ * Delete old sync runs (cleanup)
82289
+ */
82290
+ deleteOlderThan(days) {
82291
+ const result = this.db.getDb().prepare(`
82292
+ DELETE FROM sync_run_logs
82293
+ WHERE started_at < datetime('now', '-' || ? || ' days')
82294
+ `).run(days);
82295
+ return result.changes;
82296
+ }
82297
+ /**
82298
+ * Convert database row to SyncRun
82299
+ */
82300
+ rowToRun(row) {
82301
+ return {
82302
+ id: row.id,
82303
+ sourceConnectionId: row.source_connection_id || void 0,
82304
+ targetConnectionId: row.target_connection_id || void 0,
82305
+ schemaName: row.schema_name || void 0,
82306
+ tableName: row.table_name || void 0,
82307
+ groupId: row.group_id || void 0,
82308
+ startedAt: new Date(row.started_at),
82309
+ completedAt: row.completed_at ? new Date(row.completed_at) : void 0,
82310
+ status: row.status,
82311
+ inserts: row.inserts,
82312
+ updates: row.updates,
82313
+ deletes: row.deletes,
82314
+ errors: row.errors_json ? JSON.parse(row.errors_json) : [],
82315
+ sqlStatements: row.sql_statements ? JSON.parse(row.sql_statements) : [],
82316
+ sourceConnectionName: row.source_connection_name,
82317
+ targetConnectionName: row.target_connection_name,
82318
+ groupName: row.group_name
82319
+ };
82320
+ }
82321
+ };
82322
+
82323
+ // packages/metadata/dist/repositories/schema-snapshot.repository.js
82324
+ var SchemaSnapshotRepository = class {
82325
+ db;
82326
+ constructor(db) {
82327
+ this.db = db;
82328
+ }
82329
+ /**
82330
+ * Create a new schema snapshot
82331
+ */
82332
+ create(input) {
82333
+ const id = crypto.randomUUID();
82334
+ const schemaJsonStr = JSON.stringify(input.schemaJson);
82335
+ this.db.getDb().prepare(`
82336
+ INSERT INTO schema_snapshots (id, connection_id, schema_json)
82337
+ VALUES (?, ?, ?)
82338
+ `).run(id, input.connectionId, schemaJsonStr);
82339
+ return this.findById(id);
82340
+ }
82341
+ /**
82342
+ * Find a snapshot by ID
82343
+ */
82344
+ findById(id) {
82345
+ const row = this.db.getDb().prepare(`
82346
+ SELECT
82347
+ ss.*,
82348
+ c.name as connection_name
82349
+ FROM schema_snapshots ss
82350
+ LEFT JOIN connections c ON ss.connection_id = c.id
82351
+ WHERE ss.id = ?
82352
+ `).get(id);
82353
+ return row ? this.rowToSnapshot(row) : null;
82354
+ }
82355
+ /**
82356
+ * Find snapshots by connection ID
82357
+ */
82358
+ findByConnectionId(connectionId, limit) {
82359
+ let query = `
82360
+ SELECT
82361
+ ss.*,
82362
+ c.name as connection_name
82363
+ FROM schema_snapshots ss
82364
+ LEFT JOIN connections c ON ss.connection_id = c.id
82365
+ WHERE ss.connection_id = ?
82366
+ ORDER BY ss.captured_at DESC
82367
+ `;
82368
+ if (limit) {
82369
+ query += ` LIMIT ${limit}`;
82370
+ }
82371
+ const rows = this.db.getDb().prepare(query).all(connectionId);
82372
+ return rows.map((row) => this.rowToSnapshot(row));
82373
+ }
82374
+ /**
82375
+ * Find the latest snapshot for a connection
82376
+ */
82377
+ findLatest(connectionId) {
82378
+ const row = this.db.getDb().prepare(`
82379
+ SELECT
82380
+ ss.*,
82381
+ c.name as connection_name
82382
+ FROM schema_snapshots ss
82383
+ LEFT JOIN connections c ON ss.connection_id = c.id
82384
+ WHERE ss.connection_id = ?
82385
+ ORDER BY ss.captured_at DESC
82386
+ LIMIT 1
82387
+ `).get(connectionId);
82388
+ return row ? this.rowToSnapshot(row) : null;
82389
+ }
82390
+ /**
82391
+ * Find all snapshots
82392
+ */
82393
+ findAll(limit = 100) {
82394
+ const rows = this.db.getDb().prepare(`
82395
+ SELECT
82396
+ ss.*,
82397
+ c.name as connection_name
82398
+ FROM schema_snapshots ss
82399
+ LEFT JOIN connections c ON ss.connection_id = c.id
82400
+ ORDER BY ss.captured_at DESC
82401
+ LIMIT ?
82402
+ `).all(limit);
82403
+ return rows.map((row) => this.rowToSnapshot(row));
82404
+ }
82405
+ /**
82406
+ * Delete a snapshot
82407
+ */
82408
+ delete(id) {
82409
+ const result = this.db.getDb().prepare("DELETE FROM schema_snapshots WHERE id = ?").run(id);
82410
+ return result.changes > 0;
82411
+ }
82412
+ /**
82413
+ * Delete snapshots older than N days
82414
+ */
82415
+ deleteOlderThan(days) {
82416
+ const result = this.db.getDb().prepare(`
82417
+ DELETE FROM schema_snapshots
82418
+ WHERE captured_at < datetime('now', '-' || ? || ' days')
82419
+ `).run(days);
82420
+ return result.changes;
82421
+ }
82422
+ /**
82423
+ * Delete all snapshots for a connection except the N most recent
82424
+ */
82425
+ keepLatest(connectionId, count) {
82426
+ const result = this.db.getDb().prepare(`
82427
+ DELETE FROM schema_snapshots
82428
+ WHERE connection_id = ?
82429
+ AND id NOT IN (
82430
+ SELECT id FROM schema_snapshots
82431
+ WHERE connection_id = ?
82432
+ ORDER BY captured_at DESC
82433
+ LIMIT ?
82434
+ )
82435
+ `).run(connectionId, connectionId, count);
82436
+ return result.changes;
82437
+ }
82438
+ /**
82439
+ * Convert database row to SchemaSnapshot
82440
+ */
82441
+ rowToSnapshot(row) {
82442
+ return {
82443
+ id: row.id,
82444
+ connectionId: row.connection_id,
82445
+ capturedAt: new Date(row.captured_at),
82446
+ schemaJson: JSON.parse(row.schema_json),
82447
+ connectionName: row.connection_name
82448
+ };
82449
+ }
82450
+ };
82451
+
82452
+ // packages/metadata/dist/repositories/audit-log.repository.js
82453
+ var AuditLogRepository = class {
82454
+ db;
82455
+ constructor(db) {
82456
+ this.db = db;
82457
+ }
82458
+ /**
82459
+ * Create a new audit log entry
82460
+ */
82461
+ create(input) {
82462
+ const id = crypto.randomUUID();
82463
+ const detailsJson = input.details ? JSON.stringify(input.details) : null;
82464
+ this.db.getDb().prepare(`
82465
+ INSERT INTO audit_log (id, action, entity_type, entity_id, connection_id, details_json)
82466
+ VALUES (?, ?, ?, ?, ?, ?)
82467
+ `).run(id, input.action, input.entityType, input.entityId || null, input.connectionId || null, detailsJson);
82468
+ return this.findById(id);
82469
+ }
82470
+ /**
82471
+ * Log a sync operation start
82472
+ */
82473
+ logSyncStart(syncRunId, connectionId, details) {
82474
+ return this.create({
82475
+ action: "data_sync_started",
82476
+ entityType: "sync_run",
82477
+ entityId: syncRunId,
82478
+ connectionId,
82479
+ details
82480
+ });
82481
+ }
82482
+ /**
82483
+ * Log a sync operation completion
82484
+ */
82485
+ logSyncComplete(syncRunId, connectionId, results) {
82486
+ const hasErrors = results.errors.length > 0;
82487
+ return this.create({
82488
+ action: hasErrors ? "data_sync_failed" : "data_sync_completed",
82489
+ entityType: "sync_run",
82490
+ entityId: syncRunId,
82491
+ connectionId,
82492
+ details: results
82493
+ });
82494
+ }
82495
+ /**
82496
+ * Log a schema migration
82497
+ */
82498
+ logMigration(migrationId, targetConnectionId, details) {
82499
+ return this.create({
82500
+ action: "schema_migration_applied",
82501
+ entityType: "migration",
82502
+ entityId: migrationId,
82503
+ connectionId: targetConnectionId,
82504
+ details
82505
+ });
82506
+ }
82507
+ /**
82508
+ * Log a query execution
82509
+ */
82510
+ logQuery(connectionId, details) {
82511
+ return this.create({
82512
+ action: "query_executed",
82513
+ entityType: "query",
82514
+ connectionId,
82515
+ details
82516
+ });
82517
+ }
82518
+ /**
82519
+ * Find an entry by ID
82520
+ */
82521
+ findById(id) {
82522
+ const row = this.db.getDb().prepare(`
82523
+ SELECT
82524
+ al.*,
82525
+ c.name as connection_name
82526
+ FROM audit_log al
82527
+ LEFT JOIN connections c ON al.connection_id = c.id
82528
+ WHERE al.id = ?
82529
+ `).get(id);
82530
+ return row ? this.rowToEntry(row) : null;
82531
+ }
82532
+ /**
82533
+ * Find entries by connection ID
82534
+ */
82535
+ findByConnectionId(connectionId, limit) {
82536
+ let query = `
82537
+ SELECT
82538
+ al.*,
82539
+ c.name as connection_name
82540
+ FROM audit_log al
82541
+ LEFT JOIN connections c ON al.connection_id = c.id
82542
+ WHERE al.connection_id = ?
82543
+ ORDER BY al.created_at DESC
82544
+ `;
82545
+ if (limit) {
82546
+ query += ` LIMIT ${limit}`;
82547
+ }
82548
+ const rows = this.db.getDb().prepare(query).all(connectionId);
82549
+ return rows.map((row) => this.rowToEntry(row));
82550
+ }
82551
+ /**
82552
+ * Find entries by action type
82553
+ */
82554
+ findByAction(action, limit) {
82555
+ let query = `
82556
+ SELECT
82557
+ al.*,
82558
+ c.name as connection_name
82559
+ FROM audit_log al
82560
+ LEFT JOIN connections c ON al.connection_id = c.id
82561
+ WHERE al.action = ?
82562
+ ORDER BY al.created_at DESC
82563
+ `;
82564
+ if (limit) {
82565
+ query += ` LIMIT ${limit}`;
82566
+ }
82567
+ const rows = this.db.getDb().prepare(query).all(action);
82568
+ return rows.map((row) => this.rowToEntry(row));
82569
+ }
82570
+ /**
82571
+ * Find entries by entity
82572
+ */
82573
+ findByEntity(entityType, entityId) {
82574
+ const rows = this.db.getDb().prepare(`
82575
+ SELECT
82576
+ al.*,
82577
+ c.name as connection_name
82578
+ FROM audit_log al
82579
+ LEFT JOIN connections c ON al.connection_id = c.id
82580
+ WHERE al.entity_type = ? AND al.entity_id = ?
82581
+ ORDER BY al.created_at DESC
82582
+ `).all(entityType, entityId);
82583
+ return rows.map((row) => this.rowToEntry(row));
82584
+ }
82585
+ /**
82586
+ * Find all entries with optional filters
82587
+ */
82588
+ findAll(params) {
82589
+ const conditions = [];
82590
+ const values = [];
82591
+ if (params?.connectionId) {
82592
+ conditions.push("al.connection_id = ?");
82593
+ values.push(params.connectionId);
82594
+ }
82595
+ if (params?.entityType) {
82596
+ conditions.push("al.entity_type = ?");
82597
+ values.push(params.entityType);
82598
+ }
82599
+ if (params?.action) {
82600
+ conditions.push("al.action = ?");
82601
+ values.push(params.action);
82602
+ }
82603
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
82604
+ const limit = params?.limit || 500;
82605
+ const query = `
82606
+ SELECT
82607
+ al.*,
82608
+ c.name as connection_name
82609
+ FROM audit_log al
82610
+ LEFT JOIN connections c ON al.connection_id = c.id
82611
+ ${whereClause}
82612
+ ORDER BY al.created_at DESC
82613
+ LIMIT ?
82614
+ `;
82615
+ values.push(limit);
82616
+ const rows = this.db.getDb().prepare(query).all(...values);
82617
+ return rows.map((row) => this.rowToEntry(row));
82618
+ }
82619
+ /**
82620
+ * Find recent entries
82621
+ */
82622
+ findRecent(limit = 100) {
82623
+ const rows = this.db.getDb().prepare(`
82624
+ SELECT
82625
+ al.*,
82626
+ c.name as connection_name
82627
+ FROM audit_log al
82628
+ LEFT JOIN connections c ON al.connection_id = c.id
82629
+ ORDER BY al.created_at DESC
82630
+ LIMIT ?
82631
+ `).all(limit);
82632
+ return rows.map((row) => this.rowToEntry(row));
82633
+ }
82634
+ /**
82635
+ * Delete entries older than N days
82636
+ */
82637
+ deleteOlderThan(days) {
82638
+ const result = this.db.getDb().prepare(`
82639
+ DELETE FROM audit_log
82640
+ WHERE created_at < datetime('now', '-' || ? || ' days')
82641
+ `).run(days);
82642
+ return result.changes;
82643
+ }
82644
+ /**
82645
+ * Convert database row to AuditLogEntry
82646
+ */
82647
+ rowToEntry(row) {
82648
+ return {
82649
+ id: row.id,
82650
+ action: row.action,
82651
+ entityType: row.entity_type,
82652
+ entityId: row.entity_id || void 0,
82653
+ connectionId: row.connection_id || void 0,
82654
+ details: row.details_json ? JSON.parse(row.details_json) : void 0,
82655
+ createdAt: new Date(row.created_at),
82656
+ connectionName: row.connection_name
82657
+ };
82658
+ }
82659
+ };
82660
+
81989
82661
  // apps/api/dist/metadata/metadata.service.js
81990
82662
  import * as path from "node:path";
81991
82663
  import * as fs from "node:fs";
@@ -82000,10 +82672,13 @@ var MetadataService = MetadataService_1 = class MetadataService2 {
82000
82672
  logger = new import_common.Logger(MetadataService_1.name);
82001
82673
  db;
82002
82674
  _connectionRepository;
82003
- _queryRepository;
82004
- _migrationHistoryRepository;
82675
+ _queryLogsRepository;
82676
+ _migrationLogsRepository;
82005
82677
  _projectRepository;
82006
82678
  _databaseGroupRepository;
82679
+ _syncRunLogsRepository;
82680
+ _schemaSnapshotRepository;
82681
+ _auditLogRepository;
82007
82682
  onModuleInit() {
82008
82683
  let dbnexusDir;
82009
82684
  if (process.env["DBNEXUS_DATA_DIR"]) {
@@ -82022,10 +82697,13 @@ var MetadataService = MetadataService_1 = class MetadataService2 {
82022
82697
  this.db = new MetadataDatabase(dbPath);
82023
82698
  this.db.initialize();
82024
82699
  this._connectionRepository = new ConnectionRepository(this.db);
82025
- this._queryRepository = new QueryRepository(this.db);
82026
- this._migrationHistoryRepository = new MigrationHistoryRepository(this.db);
82700
+ this._queryLogsRepository = new QueryLogsRepository(this.db);
82701
+ this._migrationLogsRepository = new MigrationLogsRepository(this.db);
82027
82702
  this._projectRepository = new ProjectRepository(this.db);
82028
82703
  this._databaseGroupRepository = new DatabaseGroupRepository(this.db);
82704
+ this._syncRunLogsRepository = new SyncRunLogsRepository(this.db);
82705
+ this._schemaSnapshotRepository = new SchemaSnapshotRepository(this.db);
82706
+ this._auditLogRepository = new AuditLogRepository(this.db);
82029
82707
  this.logger.log(`\u{1F4E6} Metadata database initialized at ${dbPath}`);
82030
82708
  }
82031
82709
  onModuleDestroy() {
@@ -82034,11 +82712,11 @@ var MetadataService = MetadataService_1 = class MetadataService2 {
82034
82712
  get connectionRepository() {
82035
82713
  return this._connectionRepository;
82036
82714
  }
82037
- get queryRepository() {
82038
- return this._queryRepository;
82715
+ get queryLogsRepository() {
82716
+ return this._queryLogsRepository;
82039
82717
  }
82040
- get migrationHistoryRepository() {
82041
- return this._migrationHistoryRepository;
82718
+ get migrationLogsRepository() {
82719
+ return this._migrationLogsRepository;
82042
82720
  }
82043
82721
  get projectRepository() {
82044
82722
  return this._projectRepository;
@@ -82046,6 +82724,15 @@ var MetadataService = MetadataService_1 = class MetadataService2 {
82046
82724
  get databaseGroupRepository() {
82047
82725
  return this._databaseGroupRepository;
82048
82726
  }
82727
+ get syncRunLogsRepository() {
82728
+ return this._syncRunLogsRepository;
82729
+ }
82730
+ get schemaSnapshotRepository() {
82731
+ return this._schemaSnapshotRepository;
82732
+ }
82733
+ get auditLogRepository() {
82734
+ return this._auditLogRepository;
82735
+ }
82049
82736
  get database() {
82050
82737
  return this.db;
82051
82738
  }
@@ -83088,6 +83775,18 @@ var ConnectionsService = ConnectionsService_1 = class ConnectionsService2 {
83088
83775
  }
83089
83776
  const connection = this.metadataService.connectionRepository.create(input);
83090
83777
  this.logger.log(`Created connection "${connection.name}" (${connection.id})`);
83778
+ this.metadataService.auditLogRepository.create({
83779
+ action: "connection_created",
83780
+ entityType: "connection",
83781
+ entityId: connection.id,
83782
+ connectionId: connection.id,
83783
+ details: {
83784
+ name: connection.name,
83785
+ engine: connection.engine,
83786
+ host: connection.host,
83787
+ database: connection.database
83788
+ }
83789
+ });
83091
83790
  return connection;
83092
83791
  }
83093
83792
  /**
@@ -83106,17 +83805,37 @@ var ConnectionsService = ConnectionsService_1 = class ConnectionsService2 {
83106
83805
  throw new import_common2.NotFoundException(`Connection with ID ${id} not found`);
83107
83806
  }
83108
83807
  await this.disconnect(id);
83808
+ this.metadataService.auditLogRepository.create({
83809
+ action: "connection_updated",
83810
+ entityType: "connection",
83811
+ entityId: id,
83812
+ connectionId: id,
83813
+ details: {
83814
+ name: updated.name,
83815
+ changes: input
83816
+ }
83817
+ });
83109
83818
  return updated;
83110
83819
  }
83111
83820
  /**
83112
83821
  * Delete a connection
83113
83822
  */
83114
83823
  async delete(id) {
83824
+ const connection = this.findById(id);
83115
83825
  await this.disconnect(id);
83116
83826
  const deleted = this.metadataService.connectionRepository.delete(id);
83117
83827
  if (!deleted) {
83118
83828
  throw new import_common2.NotFoundException(`Connection with ID ${id} not found`);
83119
83829
  }
83830
+ this.metadataService.auditLogRepository.create({
83831
+ action: "connection_deleted",
83832
+ entityType: "connection",
83833
+ entityId: id,
83834
+ details: {
83835
+ name: connection.name,
83836
+ engine: connection.engine
83837
+ }
83838
+ });
83120
83839
  }
83121
83840
  /**
83122
83841
  * Test a connection
@@ -83441,18 +84160,19 @@ var QueriesService = class QueriesService2 {
83441
84160
  const startTime = Date.now();
83442
84161
  try {
83443
84162
  const result = await connector.query(sql);
83444
- this.metadataService.queryRepository.addHistoryEntry({
84163
+ this.metadataService.queryLogsRepository.addHistoryEntry({
83445
84164
  connectionId,
83446
84165
  sql,
83447
84166
  executionTimeMs: result.executionTimeMs,
83448
84167
  rowCount: result.rowCount,
83449
84168
  success: true
83450
84169
  });
84170
+ this.logAuditEventFromSql(connectionId, sql);
83451
84171
  return result;
83452
84172
  } catch (error) {
83453
84173
  const executionTimeMs = Date.now() - startTime;
83454
84174
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
83455
- this.metadataService.queryRepository.addHistoryEntry({
84175
+ this.metadataService.queryLogsRepository.addHistoryEntry({
83456
84176
  connectionId,
83457
84177
  sql,
83458
84178
  executionTimeMs,
@@ -83463,28 +84183,534 @@ var QueriesService = class QueriesService2 {
83463
84183
  throw new import_common5.BadRequestException(errorMessage);
83464
84184
  }
83465
84185
  }
84186
+ /**
84187
+ * Execute maintenance operation with detailed output
84188
+ */
84189
+ async executeMaintenance(connectionId, operation, target, scope) {
84190
+ const connection = this.connectionsService.findById(connectionId);
84191
+ const connector = await this.connectionsService.getConnector(connectionId);
84192
+ const startTime = Date.now();
84193
+ try {
84194
+ let command = this.getMaintenanceCommand(operation, connection.engine, target, scope || "database", connection);
84195
+ if (connection.engine === "postgres") {
84196
+ command = this.addVerboseFlag(operation, command);
84197
+ }
84198
+ const result = await connector.query(command);
84199
+ const duration = Date.now() - startTime;
84200
+ const { details, hasErrors } = this.extractMaintenanceDetails(result, connection.engine);
84201
+ const success = !hasErrors;
84202
+ const message = hasErrors ? `${operation.toUpperCase()} completed with errors` : `${operation.toUpperCase()} completed successfully`;
84203
+ this.metadataService.queryLogsRepository.addHistoryEntry({
84204
+ connectionId,
84205
+ sql: command,
84206
+ executionTimeMs: duration,
84207
+ rowCount: 0,
84208
+ success
84209
+ });
84210
+ return {
84211
+ success,
84212
+ message,
84213
+ details,
84214
+ duration
84215
+ };
84216
+ } catch (error) {
84217
+ const duration = Date.now() - startTime;
84218
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
84219
+ this.metadataService.queryLogsRepository.addHistoryEntry({
84220
+ connectionId,
84221
+ sql: operation,
84222
+ executionTimeMs: duration,
84223
+ rowCount: 0,
84224
+ success: false,
84225
+ error: errorMessage
84226
+ });
84227
+ throw new import_common5.BadRequestException(errorMessage);
84228
+ }
84229
+ }
84230
+ /**
84231
+ * Get maintenance command SQL
84232
+ */
84233
+ getMaintenanceCommand(operation, engine, target, scope, connection) {
84234
+ const op = operation.toLowerCase();
84235
+ if (engine === "postgres") {
84236
+ const quotePostgresIdentifier = (identifier) => {
84237
+ if (identifier.includes(".")) {
84238
+ const [schema, table] = identifier.split(".");
84239
+ return `"${schema}"."${table}"`;
84240
+ }
84241
+ return `"${identifier}"`;
84242
+ };
84243
+ switch (op) {
84244
+ case "vacuum":
84245
+ if (scope === "table" && target) {
84246
+ return `VACUUM ${quotePostgresIdentifier(target)}`;
84247
+ }
84248
+ return "VACUUM";
84249
+ case "vacuum_full":
84250
+ if (scope === "table" && target) {
84251
+ return `VACUUM (FULL) ${quotePostgresIdentifier(target)}`;
84252
+ }
84253
+ return "VACUUM (FULL)";
84254
+ case "analyze":
84255
+ if (scope === "table" && target) {
84256
+ return `ANALYZE ${quotePostgresIdentifier(target)}`;
84257
+ }
84258
+ return "ANALYZE";
84259
+ case "vacuum_analyze":
84260
+ if (scope === "table" && target) {
84261
+ return `VACUUM (ANALYZE) ${quotePostgresIdentifier(target)}`;
84262
+ }
84263
+ return "VACUUM (ANALYZE)";
84264
+ case "reindex":
84265
+ if (scope === "table" && target) {
84266
+ return `REINDEX TABLE ${quotePostgresIdentifier(target)}`;
84267
+ } else if (scope === "schema" && target) {
84268
+ return `REINDEX SCHEMA "${target}"`;
84269
+ } else {
84270
+ const dbName = connection.database || "postgres";
84271
+ return `REINDEX DATABASE "${dbName}"`;
84272
+ }
84273
+ }
84274
+ }
84275
+ if (engine === "mysql" || engine === "mariadb") {
84276
+ switch (op) {
84277
+ case "optimize":
84278
+ case "analyze_mysql":
84279
+ case "check":
84280
+ case "repair": {
84281
+ if (!target) {
84282
+ throw new import_common5.BadRequestException(`${op.toUpperCase()} requires a table name (format: schema.table)`);
84283
+ }
84284
+ let commandName;
84285
+ if (op === "analyze_mysql") {
84286
+ commandName = "ANALYZE";
84287
+ } else if (op === "optimize") {
84288
+ commandName = "OPTIMIZE";
84289
+ } else if (op === "check") {
84290
+ commandName = "CHECK";
84291
+ } else {
84292
+ commandName = "REPAIR";
84293
+ }
84294
+ return `${commandName} TABLE ${target}`;
84295
+ }
84296
+ }
84297
+ }
84298
+ if (engine === "sqlite") {
84299
+ switch (op) {
84300
+ case "vacuum":
84301
+ return "VACUUM";
84302
+ case "analyze":
84303
+ if (target) {
84304
+ return `ANALYZE "${target}"`;
84305
+ }
84306
+ return "ANALYZE";
84307
+ }
84308
+ }
84309
+ throw new import_common5.BadRequestException(`Unknown maintenance operation: ${operation} for ${engine}`);
84310
+ }
84311
+ /**
84312
+ * Add VERBOSE flag to PostgreSQL commands
84313
+ */
84314
+ addVerboseFlag(operation, command) {
84315
+ const op = operation.toLowerCase();
84316
+ if (op === "vacuum") {
84317
+ if (command.includes('"')) {
84318
+ return command.replace("VACUUM", "VACUUM (VERBOSE)");
84319
+ }
84320
+ return command.replace("VACUUM", "VACUUM (VERBOSE)");
84321
+ }
84322
+ if (op === "vacuum_full") {
84323
+ return command.replace("VACUUM (FULL)", "VACUUM (FULL, VERBOSE)");
84324
+ }
84325
+ if (op === "vacuum_analyze") {
84326
+ return command.replace("VACUUM (ANALYZE)", "VACUUM (ANALYZE, VERBOSE)");
84327
+ }
84328
+ if (op === "analyze") {
84329
+ if (command.includes('"')) {
84330
+ return command.replace("ANALYZE", "ANALYZE (VERBOSE)");
84331
+ }
84332
+ return command.replace("ANALYZE", "ANALYZE (VERBOSE)");
84333
+ }
84334
+ if (op === "reindex") {
84335
+ if (command.includes("TABLE")) {
84336
+ return command.replace("REINDEX TABLE", "REINDEX (VERBOSE) TABLE");
84337
+ } else if (command.includes("SCHEMA")) {
84338
+ return command.replace("REINDEX SCHEMA", "REINDEX (VERBOSE) SCHEMA");
84339
+ } else {
84340
+ return command.replace("REINDEX DATABASE", "REINDEX (VERBOSE) DATABASE");
84341
+ }
84342
+ }
84343
+ return command;
84344
+ }
84345
+ /**
84346
+ * Extract detailed information from maintenance operation results
84347
+ */
84348
+ extractMaintenanceDetails(result, engine) {
84349
+ const details = [];
84350
+ let hasErrors = false;
84351
+ if (engine === "postgres") {
84352
+ if (result.rows && result.rows.length > 0) {
84353
+ result.rows.forEach((row) => {
84354
+ const rowStr = JSON.stringify(row);
84355
+ if (rowStr.length > 2) {
84356
+ details.push(rowStr);
84357
+ }
84358
+ });
84359
+ }
84360
+ }
84361
+ if (engine === "mysql" && result.rows && result.rows.length > 0) {
84362
+ result.rows.forEach((row) => {
84363
+ const table = row["Table"];
84364
+ const op = row["Op"];
84365
+ const msgType = row["Msg_type"];
84366
+ const msgText = row["Msg_text"];
84367
+ if (table && op && msgType && msgText) {
84368
+ const detail = `${table} (${op}): ${msgType} - ${msgText}`;
84369
+ details.push(detail);
84370
+ const msgTypeLower = msgType.toLowerCase();
84371
+ const msgTextLower = msgText.toLowerCase();
84372
+ if (msgTypeLower === "error" || msgTypeLower === "warning" || msgTextLower.includes("failed") || msgTextLower.includes("error") || msgTextLower.includes("doesn't exist")) {
84373
+ hasErrors = true;
84374
+ }
84375
+ } else {
84376
+ details.push(JSON.stringify(row));
84377
+ }
84378
+ });
84379
+ }
84380
+ if (details.length === 0) {
84381
+ details.push(`Operation completed successfully (no detailed output available)`);
84382
+ }
84383
+ return { details, hasErrors };
84384
+ }
84385
+ /**
84386
+ * Get query execution plan
84387
+ */
84388
+ async explain(connectionId, sql, analyze = false) {
84389
+ const connection = this.connectionsService.findById(connectionId);
84390
+ const connector = await this.connectionsService.getConnector(connectionId);
84391
+ try {
84392
+ const { explainSql, parsePlan } = this.getExplainStrategy(connection.engine, sql, analyze);
84393
+ const result = await connector.query(explainSql);
84394
+ const { plan, planText } = parsePlan(result);
84395
+ const insights = this.analyzePlan(plan, connection.engine, analyze);
84396
+ const suggestions = this.generateSuggestions(plan, connection.engine);
84397
+ return { plan, planText, insights, suggestions };
84398
+ } catch (error) {
84399
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
84400
+ throw new import_common5.BadRequestException(`Failed to explain query: ${errorMessage}`);
84401
+ }
84402
+ }
84403
+ /**
84404
+ * Get database-specific EXPLAIN strategy
84405
+ */
84406
+ getExplainStrategy(engine, sql, analyze) {
84407
+ switch (engine) {
84408
+ case "postgres":
84409
+ return this.getPostgresExplainStrategy(sql, analyze);
84410
+ case "mysql":
84411
+ return this.getMysqlExplainStrategy(sql, analyze);
84412
+ case "sqlite":
84413
+ return this.getSqliteExplainStrategy(sql);
84414
+ default:
84415
+ throw new import_common5.BadRequestException(`EXPLAIN not supported for ${engine}`);
84416
+ }
84417
+ }
84418
+ /**
84419
+ * PostgreSQL EXPLAIN strategy
84420
+ */
84421
+ getPostgresExplainStrategy(sql, analyze) {
84422
+ const explainSql = analyze ? `EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS) ${sql}` : `EXPLAIN (FORMAT JSON) ${sql}`;
84423
+ const parsePlan = (result) => {
84424
+ const planJson = result.rows[0]?.["QUERY PLAN"];
84425
+ const plan = Array.isArray(planJson) ? planJson[0] : planJson;
84426
+ return {
84427
+ plan,
84428
+ planText: JSON.stringify(plan, null, 2)
84429
+ };
84430
+ };
84431
+ return { explainSql, parsePlan };
84432
+ }
84433
+ /**
84434
+ * MySQL EXPLAIN strategy
84435
+ */
84436
+ getMysqlExplainStrategy(sql, analyze) {
84437
+ if (analyze) {
84438
+ return {
84439
+ explainSql: `EXPLAIN ANALYZE ${sql}`,
84440
+ parsePlan: (result) => {
84441
+ const planText = result.rows[0]?.["EXPLAIN"] || "";
84442
+ return {
84443
+ plan: { text: planText },
84444
+ planText
84445
+ };
84446
+ }
84447
+ };
84448
+ }
84449
+ return {
84450
+ explainSql: `EXPLAIN FORMAT=JSON ${sql}`,
84451
+ parsePlan: (result) => {
84452
+ const explainData = result.rows[0]?.["EXPLAIN"];
84453
+ const planJson = typeof explainData === "string" ? JSON.parse(explainData) : explainData;
84454
+ return {
84455
+ plan: planJson,
84456
+ planText: JSON.stringify(planJson, null, 2)
84457
+ };
84458
+ }
84459
+ };
84460
+ }
84461
+ /**
84462
+ * SQLite EXPLAIN strategy
84463
+ */
84464
+ getSqliteExplainStrategy(sql) {
84465
+ return {
84466
+ explainSql: `EXPLAIN QUERY PLAN ${sql}`,
84467
+ parsePlan: (result) => {
84468
+ const planText = result.rows.map((row) => `${row["id"]} ${row["parent"]} ${row["notused"]} ${row["detail"]}`).join("\n");
84469
+ return {
84470
+ plan: result.rows,
84471
+ planText
84472
+ };
84473
+ }
84474
+ };
84475
+ }
83466
84476
  // ============ Saved Queries ============
83467
84477
  getSavedQueries() {
83468
- return this.metadataService.queryRepository.findAllSavedQueries();
84478
+ return this.metadataService.queryLogsRepository.findAllSavedQueries();
83469
84479
  }
83470
84480
  getSavedQuery(id) {
83471
- return this.metadataService.queryRepository.findSavedQueryById(id);
84481
+ return this.metadataService.queryLogsRepository.findSavedQueryById(id);
83472
84482
  }
83473
84483
  createSavedQuery(input) {
83474
- return this.metadataService.queryRepository.createSavedQuery(input);
84484
+ return this.metadataService.queryLogsRepository.createSavedQuery(input);
83475
84485
  }
83476
84486
  updateSavedQuery(id, input) {
83477
- return this.metadataService.queryRepository.updateSavedQuery(id, input);
84487
+ return this.metadataService.queryLogsRepository.updateSavedQuery(id, input);
83478
84488
  }
83479
84489
  deleteSavedQuery(id) {
83480
- return this.metadataService.queryRepository.deleteSavedQuery(id);
84490
+ return this.metadataService.queryLogsRepository.deleteSavedQuery(id);
83481
84491
  }
83482
84492
  // ============ Query History ============
83483
84493
  getHistory(connectionId, limit = 100) {
83484
- return this.metadataService.queryRepository.findRecentHistory(limit, connectionId);
84494
+ return this.metadataService.queryLogsRepository.findRecentHistory(limit, connectionId);
83485
84495
  }
83486
84496
  clearHistory(connectionId) {
83487
- return this.metadataService.queryRepository.clearHistory(connectionId);
84497
+ return this.metadataService.queryLogsRepository.clearHistory(connectionId);
84498
+ }
84499
+ // ============ Plan Analysis ============
84500
+ /**
84501
+ * Analyze query plan and generate human-friendly insights
84502
+ */
84503
+ analyzePlan(plan, engine, analyze) {
84504
+ const insights = [];
84505
+ if (engine !== "postgres" || !plan || typeof plan !== "object") {
84506
+ return insights;
84507
+ }
84508
+ const planObj = plan;
84509
+ const mainPlan = planObj["Plan"];
84510
+ if (!mainPlan)
84511
+ return insights;
84512
+ if (analyze && planObj["Execution Time"]) {
84513
+ const execTime = planObj["Execution Time"];
84514
+ if (execTime < 1) {
84515
+ insights.push({
84516
+ type: "success",
84517
+ message: `Very fast query! Executed in ${execTime.toFixed(3)}ms`
84518
+ });
84519
+ } else if (execTime < 100) {
84520
+ insights.push({
84521
+ type: "info",
84522
+ message: `Query executed in ${execTime.toFixed(2)}ms`
84523
+ });
84524
+ } else if (execTime < 1e3) {
84525
+ insights.push({
84526
+ type: "warning",
84527
+ message: `Moderately slow query: ${execTime.toFixed(0)}ms`
84528
+ });
84529
+ } else {
84530
+ insights.push({
84531
+ type: "error",
84532
+ message: `Slow query! Took ${(execTime / 1e3).toFixed(2)} seconds`
84533
+ });
84534
+ }
84535
+ }
84536
+ const seqScans = this.findSequentialScans(mainPlan);
84537
+ if (seqScans.length > 0) {
84538
+ for (const scan of seqScans) {
84539
+ const rows = scan["Plan Rows"];
84540
+ if (rows > 1e4) {
84541
+ insights.push({
84542
+ type: "warning",
84543
+ message: `Sequential scan on "${scan["Relation Name"]}" (${rows.toLocaleString()} rows). Consider adding an index if filtering.`
84544
+ });
84545
+ } else if (rows > 1e3) {
84546
+ insights.push({
84547
+ type: "info",
84548
+ message: `Sequential scan on "${scan["Relation Name"]}" (${rows.toLocaleString()} rows). This is acceptable for small tables.`
84549
+ });
84550
+ }
84551
+ }
84552
+ }
84553
+ const indexScans = this.findNodesByType(mainPlan, "Index Scan");
84554
+ if (indexScans.length > 0) {
84555
+ insights.push({
84556
+ type: "success",
84557
+ message: `Using ${indexScans.length} index scan(s) - efficient data access`
84558
+ });
84559
+ }
84560
+ const sorts = this.findNodesByType(mainPlan, "Sort");
84561
+ if (sorts.length > 0) {
84562
+ insights.push({
84563
+ type: "info",
84564
+ message: `Sorting ${sorts.length} result set(s). Add an index on ORDER BY columns to avoid sorting.`
84565
+ });
84566
+ }
84567
+ if (analyze && planObj["Planning"]) {
84568
+ const sharedHit = mainPlan["Shared Hit Blocks"] || 0;
84569
+ const sharedRead = mainPlan["Shared Read Blocks"] || 0;
84570
+ if (sharedRead > 0) {
84571
+ insights.push({
84572
+ type: "warning",
84573
+ message: `Query read ${sharedRead} block(s) from disk. Repeated queries will be faster (cached).`
84574
+ });
84575
+ } else if (sharedHit > 0) {
84576
+ insights.push({
84577
+ type: "success",
84578
+ message: `All data read from cache (${sharedHit} blocks). No disk I/O needed!`
84579
+ });
84580
+ }
84581
+ }
84582
+ return insights;
84583
+ }
84584
+ /**
84585
+ * Generate optimization suggestions based on plan analysis
84586
+ */
84587
+ generateSuggestions(plan, engine) {
84588
+ const suggestions = [];
84589
+ if (engine !== "postgres" || !plan || typeof plan !== "object") {
84590
+ return suggestions;
84591
+ }
84592
+ const planObj = plan;
84593
+ const mainPlan = planObj["Plan"];
84594
+ if (!mainPlan)
84595
+ return suggestions;
84596
+ const seqScans = this.findSequentialScans(mainPlan);
84597
+ for (const scan of seqScans) {
84598
+ const rows = scan["Plan Rows"];
84599
+ const tableName = scan["Relation Name"];
84600
+ if (rows > 1e4) {
84601
+ suggestions.push(`Consider adding an index on "${tableName}" for WHERE clause columns`);
84602
+ }
84603
+ }
84604
+ const sorts = this.findNodesByType(mainPlan, "Sort");
84605
+ if (sorts.length > 0) {
84606
+ suggestions.push("Add indexes on columns used in ORDER BY to eliminate sorting overhead");
84607
+ }
84608
+ const totalRows = mainPlan["Plan Rows"];
84609
+ if (totalRows > 1e5 && mainPlan["Node Type"] !== "Limit") {
84610
+ suggestions.push("Consider adding a LIMIT clause if you don't need all rows (reduces memory usage)");
84611
+ }
84612
+ const nestedLoops = this.findNodesByType(mainPlan, "Nested Loop");
84613
+ if (nestedLoops.length > 0) {
84614
+ for (const loop of nestedLoops) {
84615
+ const rows = loop["Plan Rows"];
84616
+ if (rows > 1e4) {
84617
+ suggestions.push("Large nested loop detected. Consider using a Hash Join or adding indexes on join columns");
84618
+ break;
84619
+ }
84620
+ }
84621
+ }
84622
+ if (suggestions.length === 0) {
84623
+ suggestions.push("Query plan looks good! No obvious optimization opportunities.");
84624
+ }
84625
+ return suggestions;
84626
+ }
84627
+ /**
84628
+ * Find all sequential scan nodes in the plan
84629
+ */
84630
+ findSequentialScans(node) {
84631
+ return this.findNodesByType(node, "Seq Scan");
84632
+ }
84633
+ /**
84634
+ * Recursively find all nodes of a specific type
84635
+ */
84636
+ findNodesByType(node, nodeType) {
84637
+ const results = [];
84638
+ if (node["Node Type"] === nodeType) {
84639
+ results.push(node);
84640
+ }
84641
+ if (Array.isArray(node["Plans"])) {
84642
+ for (const childPlan of node["Plans"]) {
84643
+ results.push(...this.findNodesByType(childPlan, nodeType));
84644
+ }
84645
+ }
84646
+ return results;
84647
+ }
84648
+ /**
84649
+ * Log audit events for high-level DDL operations
84650
+ */
84651
+ logAuditEventFromSql(connectionId, sql) {
84652
+ const normalized = sql.trim().toUpperCase();
84653
+ const extractTableName = (pattern) => {
84654
+ const match = sql.match(pattern);
84655
+ return match ? match[1].replace(/[`"'[\]]/g, "") : null;
84656
+ };
84657
+ if (normalized.startsWith("CREATE TABLE")) {
84658
+ const tableName = extractTableName(/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?([^\s(]+)/i);
84659
+ if (tableName) {
84660
+ this.metadataService.auditLogRepository.create({
84661
+ action: "table_created",
84662
+ entityType: "table",
84663
+ connectionId,
84664
+ details: { tableName, sql: sql.substring(0, 200) }
84665
+ });
84666
+ }
84667
+ } else if (normalized.startsWith("DROP TABLE")) {
84668
+ const tableName = extractTableName(/DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?([^\s;]+)/i);
84669
+ if (tableName) {
84670
+ this.metadataService.auditLogRepository.create({
84671
+ action: "table_dropped",
84672
+ entityType: "table",
84673
+ connectionId,
84674
+ details: { tableName }
84675
+ });
84676
+ }
84677
+ } else if (normalized.includes("ALTER TABLE") && normalized.includes("ADD COLUMN")) {
84678
+ const tableName = extractTableName(/ALTER\s+TABLE\s+([^\s]+)\s+ADD\s+COLUMN/i);
84679
+ const columnMatch = sql.match(/ADD\s+COLUMN\s+([^\s(]+)/i);
84680
+ const columnName = columnMatch ? columnMatch[1].replace(/[`"'[\]]/g, "") : null;
84681
+ if (tableName && columnName) {
84682
+ this.metadataService.auditLogRepository.create({
84683
+ action: "column_added",
84684
+ entityType: "column",
84685
+ connectionId,
84686
+ details: { tableName, columnName }
84687
+ });
84688
+ }
84689
+ } else if (normalized.includes("ALTER TABLE") && normalized.includes("DROP COLUMN")) {
84690
+ const tableName = extractTableName(/ALTER\s+TABLE\s+([^\s]+)\s+DROP\s+COLUMN/i);
84691
+ const columnMatch = sql.match(/DROP\s+COLUMN\s+([^\s,;]+)/i);
84692
+ const columnName = columnMatch ? columnMatch[1].replace(/[`"'[\]]/g, "") : null;
84693
+ if (tableName && columnName) {
84694
+ this.metadataService.auditLogRepository.create({
84695
+ action: "column_dropped",
84696
+ entityType: "column",
84697
+ connectionId,
84698
+ details: { tableName, columnName }
84699
+ });
84700
+ }
84701
+ } else if (normalized.includes("ALTER TABLE") && (normalized.includes("ALTER COLUMN") || normalized.includes("MODIFY COLUMN"))) {
84702
+ const tableName = extractTableName(/ALTER\s+TABLE\s+([^\s]+)/i);
84703
+ const columnMatch = sql.match(/(?:ALTER|MODIFY)\s+COLUMN\s+([^\s(]+)/i);
84704
+ const columnName = columnMatch ? columnMatch[1].replace(/[`"'[\]]/g, "") : null;
84705
+ if (tableName && columnName) {
84706
+ this.metadataService.auditLogRepository.create({
84707
+ action: "column_modified",
84708
+ entityType: "column",
84709
+ connectionId,
84710
+ details: { tableName, columnName }
84711
+ });
84712
+ }
84713
+ }
83488
84714
  }
83489
84715
  };
83490
84716
  QueriesService = __decorate6([
@@ -83518,6 +84744,12 @@ var QueriesController = class QueriesController2 {
83518
84744
  async execute(input) {
83519
84745
  return this.queriesService.execute(input);
83520
84746
  }
84747
+ async executeMaintenance(input) {
84748
+ return this.queriesService.executeMaintenance(input.connectionId, input.operation, input.target, input.scope);
84749
+ }
84750
+ async explain(input) {
84751
+ return this.queriesService.explain(input.connectionId, input.sql, input.analyze);
84752
+ }
83521
84753
  validate(input) {
83522
84754
  return this.queriesService.validate(input.connectionId, input.sql);
83523
84755
  }
@@ -83554,6 +84786,20 @@ __decorate7([
83554
84786
  __metadata5("design:paramtypes", [Object]),
83555
84787
  __metadata5("design:returntype", Promise)
83556
84788
  ], QueriesController.prototype, "execute", null);
84789
+ __decorate7([
84790
+ (0, import_common6.Post)("maintenance"),
84791
+ __param3(0, (0, import_common6.Body)()),
84792
+ __metadata5("design:type", Function),
84793
+ __metadata5("design:paramtypes", [Object]),
84794
+ __metadata5("design:returntype", Promise)
84795
+ ], QueriesController.prototype, "executeMaintenance", null);
84796
+ __decorate7([
84797
+ (0, import_common6.Post)("explain"),
84798
+ __param3(0, (0, import_common6.Body)()),
84799
+ __metadata5("design:type", Function),
84800
+ __metadata5("design:paramtypes", [Object]),
84801
+ __metadata5("design:returntype", Promise)
84802
+ ], QueriesController.prototype, "explain", null);
83557
84803
  __decorate7([
83558
84804
  (0, import_common6.Post)("validate"),
83559
84805
  __param3(0, (0, import_common6.Body)()),
@@ -83801,16 +85047,36 @@ function normalizeDefaultForComparison(defaultValue) {
83801
85047
  }
83802
85048
  return defaultValue;
83803
85049
  }
85050
+ function getColumnDefForCreate(col, engine) {
85051
+ const quotedName = quoteIdentifier(col.name, engine);
85052
+ if (isIdentityOrSerialDefault(col.defaultValue)) {
85053
+ if (engine === "postgres") {
85054
+ const isBigInt = col.dataType.toLowerCase().includes("big");
85055
+ const baseType = isBigInt ? "BIGINT" : "INTEGER";
85056
+ return `${quotedName} ${baseType} GENERATED BY DEFAULT AS IDENTITY`;
85057
+ } else if (engine === "mysql" || engine === "mariadb") {
85058
+ const isBigInt = col.dataType.toLowerCase().includes("big");
85059
+ const baseType = isBigInt ? "BIGINT" : "INT";
85060
+ let def2 = `${quotedName} ${baseType} AUTO_INCREMENT`;
85061
+ if (!col.nullable)
85062
+ def2 += " NOT NULL";
85063
+ return def2;
85064
+ } else {
85065
+ return `${quotedName} INTEGER`;
85066
+ }
85067
+ }
85068
+ let def = `${quotedName} ${col.dataType}`;
85069
+ if (!col.nullable)
85070
+ def += " NOT NULL";
85071
+ if (col.defaultValue !== null)
85072
+ def += ` DEFAULT ${col.defaultValue}`;
85073
+ return def;
85074
+ }
83804
85075
  function generateCreateTableSql(table, engine) {
83805
85076
  const sql = [];
83806
85077
  const columnDefs = [];
83807
85078
  for (const col of table.columns) {
83808
- let def = `${quoteIdentifier(col.name, engine)} ${col.dataType}`;
83809
- if (!col.nullable)
83810
- def += " NOT NULL";
83811
- if (col.defaultValue !== null)
83812
- def += ` DEFAULT ${col.defaultValue}`;
83813
- columnDefs.push(def);
85079
+ columnDefs.push(getColumnDefForCreate(col, engine));
83814
85080
  }
83815
85081
  const primaryKey = parseColumnArray(table.primaryKey);
83816
85082
  if (primaryKey.length > 0) {
@@ -83833,7 +85099,22 @@ function generateDropTableSql(schema, table, engine) {
83833
85099
  return `DROP TABLE IF EXISTS ${quoteTable(schema, table, engine)};`;
83834
85100
  }
83835
85101
  function generateAddColumnSql(schema, table, col, engine) {
83836
- let sql = `ALTER TABLE ${quoteTable(schema, table, engine)} ADD COLUMN ${quoteIdentifier(col.name, engine)} ${col.dataType}`;
85102
+ const prefix = `ALTER TABLE ${quoteTable(schema, table, engine)} ADD COLUMN`;
85103
+ if (isIdentityOrSerialDefault(col.defaultValue)) {
85104
+ if (engine === "postgres") {
85105
+ const isBigInt = col.dataType.toLowerCase().includes("big");
85106
+ const baseType = isBigInt ? "BIGINT" : "INTEGER";
85107
+ return `${prefix} ${quoteIdentifier(col.name, engine)} ${baseType} GENERATED BY DEFAULT AS IDENTITY;`;
85108
+ } else if (engine === "mysql" || engine === "mariadb") {
85109
+ const isBigInt = col.dataType.toLowerCase().includes("big");
85110
+ const baseType = isBigInt ? "BIGINT" : "INT";
85111
+ let sql2 = `${prefix} ${quoteIdentifier(col.name, engine)} ${baseType} AUTO_INCREMENT`;
85112
+ if (!col.nullable)
85113
+ sql2 += " NOT NULL";
85114
+ return sql2 + ";";
85115
+ }
85116
+ }
85117
+ let sql = `${prefix} ${quoteIdentifier(col.name, engine)} ${col.dataType}`;
83837
85118
  if (!col.nullable)
83838
85119
  sql += " NOT NULL";
83839
85120
  if (col.defaultValue !== null)
@@ -83846,6 +85127,43 @@ function generateDropColumnSql(schema, table, columnName, engine) {
83846
85127
  function generateAlterColumnSql(schema, table, source, target, engine) {
83847
85128
  const sql = [];
83848
85129
  const prefix = `ALTER TABLE ${quoteTable(schema, table, engine)}`;
85130
+ if (source.isPrimaryKey !== target.isPrimaryKey) {
85131
+ if (engine === "postgres") {
85132
+ const likelyConstraintName = `${table}_pkey`;
85133
+ if (source.isPrimaryKey && !target.isPrimaryKey) {
85134
+ sql.push(`-- Adding primary key constraint to column "${source.name}"`, `${prefix} ADD PRIMARY KEY (${quoteIdentifier(source.name, engine)});`);
85135
+ } else if (!source.isPrimaryKey && target.isPrimaryKey) {
85136
+ sql.push(`-- WARNING: Removing primary key constraint from column "${source.name}"`, `-- This is a dangerous operation. Verify before executing!`, ``, `-- Find the actual constraint name (most likely: ${likelyConstraintName}):`, `-- SELECT constraint_name FROM information_schema.table_constraints WHERE table_schema = '${schema}' AND table_name = '${table}' AND constraint_type = 'PRIMARY KEY';`, ``, `-- Drop the primary key:`, `${prefix} DROP CONSTRAINT ${likelyConstraintName};`);
85137
+ }
85138
+ } else if (engine === "mysql" || engine === "mariadb") {
85139
+ if (source.isPrimaryKey && !target.isPrimaryKey) {
85140
+ sql.push(`-- Adding primary key constraint to column "${source.name}"`, `${prefix} ADD PRIMARY KEY (${quoteIdentifier(source.name, engine)});`);
85141
+ } else if (!source.isPrimaryKey && target.isPrimaryKey) {
85142
+ sql.push(`-- WARNING: Removing primary key from column "${source.name}"`, `${prefix} DROP PRIMARY KEY;`);
85143
+ }
85144
+ } else {
85145
+ sql.push(`-- SQLite: Cannot alter primary key. Table recreation required for column "${source.name}"`, `-- You must recreate the table with the new primary key definition`);
85146
+ }
85147
+ }
85148
+ if (source.isUnique !== target.isUnique) {
85149
+ if (target.isUnique) {
85150
+ if (engine === "postgres") {
85151
+ sql.push(`${prefix} ADD CONSTRAINT uq_${table}_${source.name} UNIQUE (${quoteIdentifier(source.name, engine)});`);
85152
+ } else if (engine === "mysql" || engine === "mariadb") {
85153
+ sql.push(`${prefix} ADD UNIQUE (${quoteIdentifier(source.name, engine)});`);
85154
+ } else {
85155
+ sql.push(`CREATE UNIQUE INDEX IF NOT EXISTS uq_${table}_${source.name} ON ${quoteIdentifier(table, engine)} (${quoteIdentifier(source.name, engine)});`);
85156
+ }
85157
+ } else {
85158
+ if (engine === "postgres") {
85159
+ sql.push(`-- ${prefix} DROP CONSTRAINT uq_${table}_${source.name}; -- Check actual constraint name in your database`);
85160
+ } else if (engine === "mysql" || engine === "mariadb") {
85161
+ sql.push(`${prefix} DROP INDEX ${quoteIdentifier(source.name, engine)};`);
85162
+ } else {
85163
+ sql.push(`DROP INDEX IF EXISTS uq_${table}_${source.name};`);
85164
+ }
85165
+ }
85166
+ }
83849
85167
  if (source.dataType.toLowerCase() !== target.dataType.toLowerCase()) {
83850
85168
  sql.push(...generateAlterColumnTypeSql(schema, table, source, engine));
83851
85169
  }
@@ -84341,7 +85659,7 @@ var SchemaController = class SchemaController2 {
84341
85659
  success = false;
84342
85660
  error = err instanceof Error ? err.message : String(err);
84343
85661
  }
84344
- return this.metadataService.migrationHistoryRepository.create({
85662
+ return this.metadataService.migrationLogsRepository.create({
84345
85663
  sourceConnectionId,
84346
85664
  targetConnectionId,
84347
85665
  sourceSchema: srcSchema,
@@ -84354,16 +85672,16 @@ var SchemaController = class SchemaController2 {
84354
85672
  }
84355
85673
  // ============ Migration History ============
84356
85674
  async getMigrationHistory(targetConnectionId, limit) {
84357
- return this.metadataService.migrationHistoryRepository.findAll({
85675
+ return this.metadataService.migrationLogsRepository.findAll({
84358
85676
  targetConnectionId,
84359
85677
  limit: limit ? parseInt(limit, 10) : void 0
84360
85678
  });
84361
85679
  }
84362
85680
  async getMigration(id) {
84363
- return this.metadataService.migrationHistoryRepository.findById(id);
85681
+ return this.metadataService.migrationLogsRepository.findById(id);
84364
85682
  }
84365
85683
  async deleteMigration(id) {
84366
- return { success: this.metadataService.migrationHistoryRepository.delete(id) };
85684
+ return { success: this.metadataService.migrationLogsRepository.delete(id) };
84367
85685
  }
84368
85686
  };
84369
85687
  __decorate11([
@@ -84553,13 +85871,47 @@ var ProjectsController = class ProjectsController2 {
84553
85871
  return this.metadataService.projectRepository.findById(id);
84554
85872
  }
84555
85873
  createProject(input) {
84556
- return this.metadataService.projectRepository.create(input);
85874
+ const project = this.metadataService.projectRepository.create(input);
85875
+ this.metadataService.auditLogRepository.create({
85876
+ action: "project_created",
85877
+ entityType: "project",
85878
+ entityId: project.id,
85879
+ details: {
85880
+ name: project.name,
85881
+ description: project.description
85882
+ }
85883
+ });
85884
+ return project;
84557
85885
  }
84558
85886
  updateProject(id, input) {
84559
- return this.metadataService.projectRepository.update(id, input);
85887
+ const project = this.metadataService.projectRepository.update(id, input);
85888
+ if (project) {
85889
+ this.metadataService.auditLogRepository.create({
85890
+ action: "project_updated",
85891
+ entityType: "project",
85892
+ entityId: id,
85893
+ details: {
85894
+ name: project.name,
85895
+ changes: input
85896
+ }
85897
+ });
85898
+ }
85899
+ return project;
84560
85900
  }
84561
85901
  deleteProject(id) {
84562
- return { success: this.metadataService.projectRepository.delete(id) };
85902
+ const project = this.metadataService.projectRepository.findById(id);
85903
+ const success = this.metadataService.projectRepository.delete(id);
85904
+ if (success && project) {
85905
+ this.metadataService.auditLogRepository.create({
85906
+ action: "project_deleted",
85907
+ entityType: "project",
85908
+ entityId: id,
85909
+ details: {
85910
+ name: project.name
85911
+ }
85912
+ });
85913
+ }
85914
+ return { success };
84563
85915
  }
84564
85916
  // ============ Database Groups ============
84565
85917
  getGroups(projectId) {
@@ -84569,16 +85921,50 @@ var ProjectsController = class ProjectsController2 {
84569
85921
  return this.metadataService.databaseGroupRepository.findById(groupId);
84570
85922
  }
84571
85923
  createGroup(projectId, input) {
84572
- return this.metadataService.databaseGroupRepository.create({
85924
+ const group = this.metadataService.databaseGroupRepository.create({
84573
85925
  ...input,
84574
85926
  projectId
84575
85927
  });
85928
+ this.metadataService.auditLogRepository.create({
85929
+ action: "database_group_created",
85930
+ entityType: "database_group",
85931
+ entityId: group.id,
85932
+ details: {
85933
+ name: group.name,
85934
+ projectId: group.projectId
85935
+ }
85936
+ });
85937
+ return group;
84576
85938
  }
84577
85939
  updateGroup(_projectId, groupId, input) {
84578
- return this.metadataService.databaseGroupRepository.update(groupId, input);
85940
+ const group = this.metadataService.databaseGroupRepository.update(groupId, input);
85941
+ if (group) {
85942
+ this.metadataService.auditLogRepository.create({
85943
+ action: "database_group_updated",
85944
+ entityType: "database_group",
85945
+ entityId: groupId,
85946
+ details: {
85947
+ name: group.name,
85948
+ changes: input
85949
+ }
85950
+ });
85951
+ }
85952
+ return group;
84579
85953
  }
84580
85954
  deleteGroup(_projectId, groupId) {
84581
- return { success: this.metadataService.databaseGroupRepository.delete(groupId) };
85955
+ const group = this.metadataService.databaseGroupRepository.findById(groupId);
85956
+ const success = this.metadataService.databaseGroupRepository.delete(groupId);
85957
+ if (success && group) {
85958
+ this.metadataService.auditLogRepository.create({
85959
+ action: "database_group_deleted",
85960
+ entityType: "database_group",
85961
+ entityId: groupId,
85962
+ details: {
85963
+ name: group.name
85964
+ }
85965
+ });
85966
+ }
85967
+ return { success };
84582
85968
  }
84583
85969
  // ============ Connections in Project/Group ============
84584
85970
  getProjectConnections(projectId) {
@@ -84779,6 +86165,40 @@ function isJsonColumn(dataType) {
84779
86165
  const typeLower = dataType.toLowerCase();
84780
86166
  return typeLower === "json" || typeLower === "jsonb";
84781
86167
  }
86168
+ function formatValueForSql(value) {
86169
+ if (value === null || value === void 0) {
86170
+ return "NULL";
86171
+ }
86172
+ if (typeof value === "string") {
86173
+ return `'${value.replace(/'/g, "''")}'`;
86174
+ }
86175
+ if (typeof value === "number" || typeof value === "bigint") {
86176
+ return String(value);
86177
+ }
86178
+ if (typeof value === "boolean") {
86179
+ return value ? "TRUE" : "FALSE";
86180
+ }
86181
+ if (value instanceof Date) {
86182
+ return `'${value.toISOString()}'`;
86183
+ }
86184
+ if (typeof value === "object") {
86185
+ return `'${JSON.stringify(value).replace(/'/g, "''")}'`;
86186
+ }
86187
+ return String(value);
86188
+ }
86189
+ function buildReadableSql(template, values, engine) {
86190
+ let sql = template;
86191
+ if (engine === "mysql" || engine === "mariadb") {
86192
+ for (const value of values) {
86193
+ sql = sql.replace("?", formatValueForSql(value));
86194
+ }
86195
+ } else {
86196
+ for (let i = values.length; i >= 1; i--) {
86197
+ sql = sql.replace(`$${i}`, formatValueForSql(values[i - 1]));
86198
+ }
86199
+ }
86200
+ return sql;
86201
+ }
84782
86202
  function serializeValueForInsert(value, dataType) {
84783
86203
  if (value === null || value === void 0) {
84784
86204
  return value;
@@ -84979,17 +86399,21 @@ var SyncService = SyncService_1 = class SyncService2 {
84979
86399
  * Get detailed data diff for a specific table
84980
86400
  */
84981
86401
  async getTableDataDiff(sourceConnectionId, targetConnectionId, schema, table, primaryKeyColumns) {
86402
+ const pkColumns = parseColumnArray(primaryKeyColumns);
86403
+ if (pkColumns.length === 0) {
86404
+ throw new Error("No primary key columns provided");
86405
+ }
84982
86406
  const sourceConnection = this.connectionsService.findById(sourceConnectionId);
84983
86407
  const targetConnection = this.connectionsService.findById(targetConnectionId);
84984
86408
  const sourceConnector = await this.connectionsService.getConnector(sourceConnectionId);
84985
86409
  const targetConnector = await this.connectionsService.getConnector(targetConnectionId);
84986
86410
  const sourceTableRef = quoteTableRef(schema, table, sourceConnection.engine);
84987
86411
  const targetTableRef = quoteTableRef(schema, table, targetConnection.engine);
84988
- const sourceOrderBy = primaryKeyColumns.map((c) => quoteIdentifier2(c, sourceConnection.engine)).join(", ");
84989
- const targetOrderBy = primaryKeyColumns.map((c) => quoteIdentifier2(c, targetConnection.engine)).join(", ");
86412
+ const sourceOrderBy = pkColumns.map((c) => quoteIdentifier2(c, sourceConnection.engine)).join(", ");
86413
+ const targetOrderBy = pkColumns.map((c) => quoteIdentifier2(c, targetConnection.engine)).join(", ");
84990
86414
  const sourceResult = await sourceConnector.query(`SELECT * FROM ${sourceTableRef} ORDER BY ${sourceOrderBy}`);
84991
86415
  const targetResult = await targetConnector.query(`SELECT * FROM ${targetTableRef} ORDER BY ${targetOrderBy}`);
84992
- const getPkValue = (row) => primaryKeyColumns.map((c) => String(row[c])).join("|");
86416
+ const getPkValue = (row) => pkColumns.map((c) => String(row[c])).join("|");
84993
86417
  const sourceMap = /* @__PURE__ */ new Map();
84994
86418
  const targetMap = /* @__PURE__ */ new Map();
84995
86419
  for (const row of sourceResult.rows) {
@@ -85030,7 +86454,26 @@ var SyncService = SyncService_1 = class SyncService2 {
85030
86454
  };
85031
86455
  const targetConnection = this.connectionsService.findById(targetConnectionId);
85032
86456
  const targetConnector = await this.connectionsService.getConnector(targetConnectionId);
85033
- const diff = await this.getTableDataDiff(sourceConnectionId, targetConnectionId, schema, table, primaryKeyColumns);
86457
+ const parsedPkColumns = parseColumnArray(primaryKeyColumns);
86458
+ let effectivePkColumns = parsedPkColumns;
86459
+ if (parsedPkColumns.length === 0 || parsedPkColumns.length === 1 && parsedPkColumns[0] === "id") {
86460
+ const tableSchema2 = await targetConnector.getTableSchema(schema, table);
86461
+ const schemaPks = parseColumnArray(tableSchema2.primaryKey);
86462
+ if (schemaPks.length > 0) {
86463
+ effectivePkColumns = schemaPks;
86464
+ this.logger.debug(`Auto-detected primary keys for ${schema}.${table}: ${effectivePkColumns.join(", ")}`);
86465
+ } else {
86466
+ effectivePkColumns = ["id"];
86467
+ this.logger.warn(`No primary key found for ${schema}.${table}, falling back to 'id'`);
86468
+ }
86469
+ }
86470
+ const syncRun = this.metadataService.syncRunLogsRepository.create({
86471
+ sourceConnectionId,
86472
+ targetConnectionId,
86473
+ schemaName: schema,
86474
+ tableName: table
86475
+ });
86476
+ const diff = await this.getTableDataDiff(sourceConnectionId, targetConnectionId, schema, table, effectivePkColumns);
85034
86477
  const tableSchema = await targetConnector.getTableSchema(schema, table);
85035
86478
  const columns = tableSchema.columns.map((c) => c.name);
85036
86479
  const columnTypes = new Map(tableSchema.columns.map((c) => [c.name, c.dataType]));
@@ -85041,13 +86484,16 @@ var SyncService = SyncService_1 = class SyncService2 {
85041
86484
  const dataType = columnTypes.get(colName) || "";
85042
86485
  return serializeValueForInsert(value, dataType);
85043
86486
  };
86487
+ const executedSql = [];
85044
86488
  if (options.insertMissing && diff.missingInTarget.length > 0) {
85045
86489
  for (const row of diff.missingInTarget) {
85046
86490
  try {
85047
86491
  const values = insertableColumns.map((c) => serializeValue(c, row[c]));
85048
86492
  const placeholders = insertableColumns.map((_, i) => getPlaceholder(i + 1, engine)).join(", ");
85049
86493
  const quotedColumns = insertableColumns.map((c) => quoteIdentifier2(c, engine)).join(", ");
85050
- await targetConnector.execute(`INSERT INTO ${tableRef} (${quotedColumns}) VALUES (${placeholders})`, values);
86494
+ const sqlTemplate = `INSERT INTO ${tableRef} (${quotedColumns}) VALUES (${placeholders})`;
86495
+ executedSql.push(buildReadableSql(sqlTemplate, values, engine));
86496
+ await targetConnector.execute(sqlTemplate, values);
85051
86497
  result.inserted++;
85052
86498
  } catch (error) {
85053
86499
  result.errors.push(`Insert failed: ${error instanceof Error ? error.message : String(error)}`);
@@ -85057,14 +86503,16 @@ var SyncService = SyncService_1 = class SyncService2 {
85057
86503
  if (options.updateDifferent && diff.different.length > 0) {
85058
86504
  for (const { source } of diff.different) {
85059
86505
  try {
85060
- const nonPkColumns = columns.filter((c) => !primaryKeyColumns.includes(c));
86506
+ const nonPkColumns = columns.filter((c) => !effectivePkColumns.includes(c));
85061
86507
  const setClause = nonPkColumns.map((c, i) => `${quoteIdentifier2(c, engine)} = ${getPlaceholder(i + 1, engine)}`).join(", ");
85062
- const whereClause = primaryKeyColumns.map((c, i) => `${quoteIdentifier2(c, engine)} = ${getPlaceholder(nonPkColumns.length + i + 1, engine)}`).join(" AND ");
86508
+ const whereClause = effectivePkColumns.map((c, i) => `${quoteIdentifier2(c, engine)} = ${getPlaceholder(nonPkColumns.length + i + 1, engine)}`).join(" AND ");
85063
86509
  const values = [
85064
86510
  ...nonPkColumns.map((c) => serializeValue(c, source[c])),
85065
- ...primaryKeyColumns.map((c) => serializeValue(c, source[c]))
86511
+ ...effectivePkColumns.map((c) => serializeValue(c, source[c]))
85066
86512
  ];
85067
- await targetConnector.execute(`UPDATE ${tableRef} SET ${setClause} WHERE ${whereClause}`, values);
86513
+ const sqlTemplate = `UPDATE ${tableRef} SET ${setClause} WHERE ${whereClause}`;
86514
+ executedSql.push(buildReadableSql(sqlTemplate, values, engine));
86515
+ await targetConnector.execute(sqlTemplate, values);
85068
86516
  result.updated++;
85069
86517
  } catch (error) {
85070
86518
  result.errors.push(`Update failed: ${error instanceof Error ? error.message : String(error)}`);
@@ -85074,15 +86522,25 @@ var SyncService = SyncService_1 = class SyncService2 {
85074
86522
  if (options.deleteExtra && diff.missingInSource.length > 0) {
85075
86523
  for (const row of diff.missingInSource) {
85076
86524
  try {
85077
- const whereClause = primaryKeyColumns.map((c, i) => `${quoteIdentifier2(c, engine)} = ${getPlaceholder(i + 1, engine)}`).join(" AND ");
85078
- const values = primaryKeyColumns.map((c) => row[c]);
85079
- await targetConnector.execute(`DELETE FROM ${tableRef} WHERE ${whereClause}`, values);
86525
+ const whereClause = effectivePkColumns.map((c, i) => `${quoteIdentifier2(c, engine)} = ${getPlaceholder(i + 1, engine)}`).join(" AND ");
86526
+ const values = effectivePkColumns.map((c) => row[c]);
86527
+ const sqlTemplate = `DELETE FROM ${tableRef} WHERE ${whereClause}`;
86528
+ executedSql.push(buildReadableSql(sqlTemplate, values, engine));
86529
+ await targetConnector.execute(sqlTemplate, values);
85080
86530
  result.deleted++;
85081
86531
  } catch (error) {
85082
86532
  result.errors.push(`Delete failed: ${error instanceof Error ? error.message : String(error)}`);
85083
86533
  }
85084
86534
  }
85085
86535
  }
86536
+ this.metadataService.syncRunLogsRepository.update(syncRun.id, {
86537
+ status: result.errors.length > 0 ? "failed" : "completed",
86538
+ inserts: result.inserted,
86539
+ updates: result.updated,
86540
+ deletes: result.deleted,
86541
+ errors: result.errors,
86542
+ sqlStatements: executedSql
86543
+ });
85086
86544
  return result;
85087
86545
  }
85088
86546
  /**
@@ -85093,6 +86551,12 @@ var SyncService = SyncService_1 = class SyncService2 {
85093
86551
  if (rowIds.length === 0 || primaryKeyColumns.length === 0) {
85094
86552
  return result;
85095
86553
  }
86554
+ const syncRun = this.metadataService.syncRunLogsRepository.create({
86555
+ sourceConnectionId,
86556
+ targetConnectionId,
86557
+ schemaName: sourceSchema,
86558
+ tableName: table
86559
+ });
85096
86560
  const sourceConnection = this.connectionsService.findById(sourceConnectionId);
85097
86561
  const targetConnection = this.connectionsService.findById(targetConnectionId);
85098
86562
  const sourceConnector = await this.connectionsService.getConnector(sourceConnectionId);
@@ -85146,6 +86610,13 @@ var SyncService = SyncService_1 = class SyncService2 {
85146
86610
  result.errors.push(`Row sync failed for ${JSON.stringify(rowId)}: ${error instanceof Error ? error.message : String(error)}`);
85147
86611
  }
85148
86612
  }
86613
+ const completedStatus = result.errors.length > 0 ? "failed" : "completed";
86614
+ const errorsJson = result.errors.length > 0 ? JSON.stringify(result.errors) : null;
86615
+ this.metadataService.database.getDb().prepare(`
86616
+ UPDATE sync_run_logs
86617
+ SET status = ?, completed_at = datetime('now'), inserts = ?, updates = ?, deletes = ?, errors_json = ?
86618
+ WHERE id = ?
86619
+ `).run(completedStatus, result.inserted, result.updated, 0, errorsJson, syncRun.id);
85149
86620
  return result;
85150
86621
  }
85151
86622
  /**
@@ -85233,6 +86704,11 @@ var SyncService = SyncService_1 = class SyncService2 {
85233
86704
  errors: [],
85234
86705
  tableResults: []
85235
86706
  };
86707
+ const syncRun = this.metadataService.syncRunLogsRepository.create({
86708
+ sourceConnectionId,
86709
+ targetConnectionId,
86710
+ schemaName: schema
86711
+ });
85236
86712
  const sourceConnection = this.connectionsService.findById(sourceConnectionId);
85237
86713
  const targetConnection = this.connectionsService.findById(targetConnectionId);
85238
86714
  const sourceConnector = await this.connectionsService.getConnector(sourceConnectionId);
@@ -85327,6 +86803,12 @@ var SyncService = SyncService_1 = class SyncService2 {
85327
86803
  } finally {
85328
86804
  await this.setForeignKeyChecks(targetConnector, targetEngine, true);
85329
86805
  }
86806
+ this.metadataService.syncRunLogsRepository.complete(syncRun.id, {
86807
+ inserts: result.rowsCopied,
86808
+ updates: 0,
86809
+ deletes: 0,
86810
+ errors: result.errors
86811
+ });
85330
86812
  return result;
85331
86813
  }
85332
86814
  /**
@@ -85372,8 +86854,16 @@ var __param6 = function(paramIndex, decorator) {
85372
86854
  };
85373
86855
  var SyncController = class SyncController2 {
85374
86856
  syncService;
85375
- constructor(syncService) {
86857
+ metadataService;
86858
+ constructor(syncService, metadataService) {
85376
86859
  this.syncService = syncService;
86860
+ this.metadataService = metadataService;
86861
+ }
86862
+ /**
86863
+ * Get recent sync runs (for activity log)
86864
+ */
86865
+ getSyncRuns(limit) {
86866
+ return this.metadataService.syncRunLogsRepository.findRecent(limit ? parseInt(limit, 10) : 500);
85377
86867
  }
85378
86868
  /**
85379
86869
  * Get sync status for an instance group
@@ -85472,6 +86962,13 @@ var SyncController = class SyncController2 {
85472
86962
  });
85473
86963
  }
85474
86964
  };
86965
+ __decorate17([
86966
+ (0, import_common16.Get)("runs"),
86967
+ __param6(0, (0, import_common16.Query)("limit")),
86968
+ __metadata11("design:type", Function),
86969
+ __metadata11("design:paramtypes", [String]),
86970
+ __metadata11("design:returntype", void 0)
86971
+ ], SyncController.prototype, "getSyncRuns", null);
85475
86972
  __decorate17([
85476
86973
  (0, import_common16.Get)("groups/:groupId/status"),
85477
86974
  __param6(0, (0, import_common16.Param)("groupId")),
@@ -85556,7 +87053,10 @@ __decorate17([
85556
87053
  ], SyncController.prototype, "dumpAndRestore", null);
85557
87054
  SyncController = __decorate17([
85558
87055
  (0, import_common16.Controller)("sync"),
85559
- __metadata11("design:paramtypes", [SyncService])
87056
+ __metadata11("design:paramtypes", [
87057
+ SyncService,
87058
+ MetadataService
87059
+ ])
85560
87060
  ], SyncController);
85561
87061
 
85562
87062
  // apps/api/dist/sync/sync.module.js
@@ -86269,18 +87769,93 @@ ScannerModule = __decorate23([
86269
87769
  })
86270
87770
  ], ScannerModule);
86271
87771
 
86272
- // apps/api/dist/app.module.js
87772
+ // apps/api/dist/audit/audit.module.js
87773
+ var import_common24 = __toESM(require_common(), 1);
87774
+
87775
+ // apps/api/dist/audit/audit.controller.js
87776
+ var import_common23 = __toESM(require_common(), 1);
86273
87777
  var __decorate24 = function(decorators, target, key, desc) {
86274
87778
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
86275
87779
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
86276
87780
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
86277
87781
  return c > 3 && r && Object.defineProperty(target, key, r), r;
86278
87782
  };
87783
+ var __metadata14 = function(k, v) {
87784
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
87785
+ };
87786
+ var __param8 = function(paramIndex, decorator) {
87787
+ return function(target, key) {
87788
+ decorator(target, key, paramIndex);
87789
+ };
87790
+ };
87791
+ var AuditController = class AuditController2 {
87792
+ metadataService;
87793
+ constructor(metadataService) {
87794
+ this.metadataService = metadataService;
87795
+ }
87796
+ getAuditLogs(connectionId, entityType, action, limitStr) {
87797
+ const limit = limitStr ? parseInt(limitStr, 10) : 500;
87798
+ return this.metadataService.auditLogRepository.findAll({
87799
+ connectionId,
87800
+ entityType,
87801
+ action,
87802
+ limit
87803
+ });
87804
+ }
87805
+ getAuditLog(id) {
87806
+ return this.metadataService.auditLogRepository.findById(id);
87807
+ }
87808
+ };
87809
+ __decorate24([
87810
+ (0, import_common23.Get)("logs"),
87811
+ __param8(0, (0, import_common23.Query)("connectionId")),
87812
+ __param8(1, (0, import_common23.Query)("entityType")),
87813
+ __param8(2, (0, import_common23.Query)("action")),
87814
+ __param8(3, (0, import_common23.Query)("limit")),
87815
+ __metadata14("design:type", Function),
87816
+ __metadata14("design:paramtypes", [String, String, String, String]),
87817
+ __metadata14("design:returntype", Array)
87818
+ ], AuditController.prototype, "getAuditLogs", null);
87819
+ __decorate24([
87820
+ (0, import_common23.Get)("logs/:id"),
87821
+ __param8(0, (0, import_common23.Query)("id")),
87822
+ __metadata14("design:type", Function),
87823
+ __metadata14("design:paramtypes", [String]),
87824
+ __metadata14("design:returntype", Object)
87825
+ ], AuditController.prototype, "getAuditLog", null);
87826
+ AuditController = __decorate24([
87827
+ (0, import_common23.Controller)("audit"),
87828
+ __metadata14("design:paramtypes", [MetadataService])
87829
+ ], AuditController);
87830
+
87831
+ // apps/api/dist/audit/audit.module.js
87832
+ var __decorate25 = function(decorators, target, key, desc) {
87833
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
87834
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
87835
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
87836
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
87837
+ };
87838
+ var AuditModule = class AuditModule2 {
87839
+ };
87840
+ AuditModule = __decorate25([
87841
+ (0, import_common24.Module)({
87842
+ imports: [MetadataModule],
87843
+ controllers: [AuditController]
87844
+ })
87845
+ ], AuditModule);
87846
+
87847
+ // apps/api/dist/app.module.js
87848
+ var __decorate26 = function(decorators, target, key, desc) {
87849
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
87850
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
87851
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
87852
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
87853
+ };
86279
87854
  var __dirname = fileURLToPath(new URL(".", import.meta.url));
86280
87855
  var AppModule = class AppModule2 {
86281
87856
  };
86282
- AppModule = __decorate24([
86283
- (0, import_common23.Module)({
87857
+ AppModule = __decorate26([
87858
+ (0, import_common25.Module)({
86284
87859
  imports: [
86285
87860
  // Serve static files from web build in production
86286
87861
  ...true ? [
@@ -86296,7 +87871,8 @@ AppModule = __decorate24([
86296
87871
  ProjectsModule,
86297
87872
  SyncModule,
86298
87873
  HealthModule,
86299
- ScannerModule
87874
+ ScannerModule,
87875
+ AuditModule
86300
87876
  ]
86301
87877
  })
86302
87878
  ], AppModule);
@@ -86308,7 +87884,7 @@ import * as fs3 from "node:fs";
86308
87884
  var __filename = fileURLToPath2(import.meta.url);
86309
87885
  var __dirname2 = path3.dirname(__filename);
86310
87886
  async function bootstrap() {
86311
- const logger = new import_common24.Logger("Bootstrap");
87887
+ const logger = new import_common26.Logger("Bootstrap");
86312
87888
  const app = await import_core.NestFactory.create(AppModule, {
86313
87889
  bodyParser: true
86314
87890
  });