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 +1709 -133
- package/dist/cli.js +101 -7
- package/dist/web/assets/index-SOXzwa_o.js +383 -0
- package/dist/web/assets/{index-irX5x4FY.css → index-Ypj2Gos3.css} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +2 -2
- package/dist/web/assets/index-B64mvoX2.js +0 -379
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 =
|
|
1996
|
+
exports2.Controller = Controller9;
|
|
1997
1997
|
var constants_1 = require_constants2();
|
|
1998
1998
|
var shared_utils_1 = require_shared_utils();
|
|
1999
|
-
function
|
|
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 =
|
|
2419
|
+
exports2.Module = Module11;
|
|
2420
2420
|
var validate_module_keys_util_1 = require_validate_module_keys_util();
|
|
2421
|
-
function
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
57492
|
+
exports2.ServeStaticModule = ServeStaticModule2 = ServeStaticModule_1 = __decorate27([
|
|
57493
57493
|
(0, common_1.Module)({
|
|
57494
57494
|
providers: [...serve_static_providers_1.serveStaticProviders]
|
|
57495
57495
|
}),
|
|
57496
|
-
|
|
57497
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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:
|
|
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
|
|
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
|
-
|
|
77129
|
-
module2.exports =
|
|
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
|
|
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 =
|
|
77601
|
-
Execute.prototype.doneInsert =
|
|
77602
|
-
Execute.prototype.resultsetHeader =
|
|
77603
|
-
Execute.prototype._findOrCreateReadStream =
|
|
77604
|
-
Execute.prototype._streamLocalInfile =
|
|
77605
|
-
Execute.prototype._setTimeout =
|
|
77606
|
-
Execute.prototype._handleTimeoutError =
|
|
77607
|
-
Execute.prototype.row =
|
|
77608
|
-
Execute.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
|
|
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:
|
|
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
|
|
80931
|
+
var import_common26 = __toESM(require_common(), 1);
|
|
80932
80932
|
|
|
80933
80933
|
// apps/api/dist/app.module.js
|
|
80934
|
-
var
|
|
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 =
|
|
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
|
-
|
|
81266
|
+
let currentVersion = this.getSchemaVersion();
|
|
81188
81267
|
if (currentVersion === 0) {
|
|
81189
81268
|
this.db.exec(MIGRATIONS[0]);
|
|
81190
|
-
|
|
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
|
-
|
|
81477
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
81666
|
-
var
|
|
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
|
-
|
|
81679
|
-
|
|
81680
|
-
|
|
81681
|
-
|
|
81682
|
-
|
|
81683
|
-
|
|
81684
|
-
|
|
81685
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
81734
|
-
|
|
81735
|
-
|
|
81736
|
-
|
|
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
|
|
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
|
-
|
|
82004
|
-
|
|
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.
|
|
82026
|
-
this.
|
|
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
|
|
82038
|
-
return this.
|
|
82715
|
+
get queryLogsRepository() {
|
|
82716
|
+
return this._queryLogsRepository;
|
|
82039
82717
|
}
|
|
82040
|
-
get
|
|
82041
|
-
return this.
|
|
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.
|
|
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.
|
|
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.
|
|
84478
|
+
return this.metadataService.queryLogsRepository.findAllSavedQueries();
|
|
83469
84479
|
}
|
|
83470
84480
|
getSavedQuery(id) {
|
|
83471
|
-
return this.metadataService.
|
|
84481
|
+
return this.metadataService.queryLogsRepository.findSavedQueryById(id);
|
|
83472
84482
|
}
|
|
83473
84483
|
createSavedQuery(input) {
|
|
83474
|
-
return this.metadataService.
|
|
84484
|
+
return this.metadataService.queryLogsRepository.createSavedQuery(input);
|
|
83475
84485
|
}
|
|
83476
84486
|
updateSavedQuery(id, input) {
|
|
83477
|
-
return this.metadataService.
|
|
84487
|
+
return this.metadataService.queryLogsRepository.updateSavedQuery(id, input);
|
|
83478
84488
|
}
|
|
83479
84489
|
deleteSavedQuery(id) {
|
|
83480
|
-
return this.metadataService.
|
|
84490
|
+
return this.metadataService.queryLogsRepository.deleteSavedQuery(id);
|
|
83481
84491
|
}
|
|
83482
84492
|
// ============ Query History ============
|
|
83483
84493
|
getHistory(connectionId, limit = 100) {
|
|
83484
|
-
return this.metadataService.
|
|
84494
|
+
return this.metadataService.queryLogsRepository.findRecentHistory(limit, connectionId);
|
|
83485
84495
|
}
|
|
83486
84496
|
clearHistory(connectionId) {
|
|
83487
|
-
return this.metadataService.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
85681
|
+
return this.metadataService.migrationLogsRepository.findById(id);
|
|
84364
85682
|
}
|
|
84365
85683
|
async deleteMigration(id) {
|
|
84366
|
-
return { success: this.metadataService.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
84989
|
-
const targetOrderBy =
|
|
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) =>
|
|
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
|
|
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
|
-
|
|
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) => !
|
|
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 =
|
|
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
|
-
...
|
|
86511
|
+
...effectivePkColumns.map((c) => serializeValue(c, source[c]))
|
|
85066
86512
|
];
|
|
85067
|
-
|
|
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 =
|
|
85078
|
-
const values =
|
|
85079
|
-
|
|
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
|
-
|
|
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", [
|
|
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/
|
|
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 =
|
|
86283
|
-
(0,
|
|
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
|
|
87887
|
+
const logger = new import_common26.Logger("Bootstrap");
|
|
86312
87888
|
const app = await import_core.NestFactory.create(AppModule, {
|
|
86313
87889
|
bodyParser: true
|
|
86314
87890
|
});
|