@usebetterdev/audit-drizzle 0.5.0-beta.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +439 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +322 -1
- package/dist/index.d.ts +322 -1
- package/dist/index.js +451 -0
- package/dist/index.js.map +1 -1
- package/package.json +13 -5
package/dist/index.cjs
CHANGED
|
@@ -7,11 +7,11 @@ var __export = (target, all) => {
|
|
|
7
7
|
for (var name in all)
|
|
8
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
9
|
};
|
|
10
|
-
var __copyProps = (to, from, except,
|
|
10
|
+
var __copyProps = (to, from, except, desc5) => {
|
|
11
11
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
12
|
for (let key of __getOwnPropNames(from))
|
|
13
13
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc5 = __getOwnPropDesc(from, key)) || desc5.enumerable });
|
|
15
15
|
}
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
@@ -26,7 +26,9 @@ __export(index_exports, {
|
|
|
26
26
|
buildWhereConditions: () => buildWhereConditions,
|
|
27
27
|
decodeCursor: () => decodeCursor,
|
|
28
28
|
drizzleAuditAdapter: () => drizzleAuditAdapter,
|
|
29
|
+
drizzleSqliteAuditAdapter: () => drizzleSqliteAuditAdapter,
|
|
29
30
|
encodeCursor: () => encodeCursor,
|
|
31
|
+
sqliteAuditLogs: () => sqliteAuditLogs,
|
|
30
32
|
withAuditProxy: () => withAuditProxy
|
|
31
33
|
});
|
|
32
34
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -466,8 +468,439 @@ function assembleStats(summaryRows, eventsPerDayRows, topActorsRows, topTablesRo
|
|
|
466
468
|
};
|
|
467
469
|
}
|
|
468
470
|
|
|
469
|
-
// src/
|
|
471
|
+
// src/sqlite-adapter.ts
|
|
472
|
+
var import_drizzle_orm4 = require("drizzle-orm");
|
|
473
|
+
|
|
474
|
+
// src/sqlite-schema.ts
|
|
475
|
+
var import_sqlite_core = require("drizzle-orm/sqlite-core");
|
|
476
|
+
var sqliteAuditLogs = (0, import_sqlite_core.sqliteTable)(
|
|
477
|
+
"audit_logs",
|
|
478
|
+
{
|
|
479
|
+
id: (0, import_sqlite_core.text)().primaryKey(),
|
|
480
|
+
timestamp: (0, import_sqlite_core.integer)({ mode: "timestamp" }).notNull(),
|
|
481
|
+
tableName: (0, import_sqlite_core.text)("table_name").notNull(),
|
|
482
|
+
operation: (0, import_sqlite_core.text)().notNull(),
|
|
483
|
+
recordId: (0, import_sqlite_core.text)("record_id").notNull(),
|
|
484
|
+
actorId: (0, import_sqlite_core.text)("actor_id"),
|
|
485
|
+
beforeData: (0, import_sqlite_core.text)("before_data", { mode: "json" }),
|
|
486
|
+
afterData: (0, import_sqlite_core.text)("after_data", { mode: "json" }),
|
|
487
|
+
diff: (0, import_sqlite_core.text)({ mode: "json" }),
|
|
488
|
+
label: (0, import_sqlite_core.text)(),
|
|
489
|
+
description: (0, import_sqlite_core.text)(),
|
|
490
|
+
severity: (0, import_sqlite_core.text)(),
|
|
491
|
+
compliance: (0, import_sqlite_core.text)({ mode: "json" }),
|
|
492
|
+
notify: (0, import_sqlite_core.integer)({ mode: "boolean" }),
|
|
493
|
+
reason: (0, import_sqlite_core.text)(),
|
|
494
|
+
metadata: (0, import_sqlite_core.text)({ mode: "json" }),
|
|
495
|
+
redactedFields: (0, import_sqlite_core.text)("redacted_fields", { mode: "json" })
|
|
496
|
+
},
|
|
497
|
+
(table) => ({
|
|
498
|
+
tableNameTimestampIdx: (0, import_sqlite_core.index)("audit_logs_table_name_timestamp_idx").on(
|
|
499
|
+
table.tableName,
|
|
500
|
+
table.timestamp
|
|
501
|
+
),
|
|
502
|
+
actorIdIdx: (0, import_sqlite_core.index)("audit_logs_actor_id_idx").on(table.actorId),
|
|
503
|
+
recordIdIdx: (0, import_sqlite_core.index)("audit_logs_record_id_idx").on(table.recordId),
|
|
504
|
+
tableNameRecordIdIdx: (0, import_sqlite_core.index)("audit_logs_table_name_record_id_idx").on(
|
|
505
|
+
table.tableName,
|
|
506
|
+
table.recordId
|
|
507
|
+
),
|
|
508
|
+
operationIdx: (0, import_sqlite_core.index)("audit_logs_operation_idx").on(table.operation),
|
|
509
|
+
timestampIdx: (0, import_sqlite_core.index)("audit_logs_timestamp_idx").on(table.timestamp),
|
|
510
|
+
timestampIdIdx: (0, import_sqlite_core.index)("audit_logs_timestamp_id_idx").on(table.timestamp, table.id)
|
|
511
|
+
})
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
// src/sqlite-column-map.ts
|
|
515
|
+
var VALID_OPERATIONS2 = /* @__PURE__ */ new Set([
|
|
516
|
+
"INSERT",
|
|
517
|
+
"UPDATE",
|
|
518
|
+
"DELETE"
|
|
519
|
+
]);
|
|
520
|
+
var VALID_SEVERITIES2 = /* @__PURE__ */ new Set([
|
|
521
|
+
"low",
|
|
522
|
+
"medium",
|
|
523
|
+
"high",
|
|
524
|
+
"critical"
|
|
525
|
+
]);
|
|
526
|
+
function isAuditOperation2(value) {
|
|
527
|
+
return VALID_OPERATIONS2.has(value);
|
|
528
|
+
}
|
|
529
|
+
function isAuditSeverity2(value) {
|
|
530
|
+
return VALID_SEVERITIES2.has(value);
|
|
531
|
+
}
|
|
532
|
+
function sqliteAuditLogToRow(log) {
|
|
533
|
+
const row = {
|
|
534
|
+
id: log.id,
|
|
535
|
+
timestamp: log.timestamp,
|
|
536
|
+
tableName: log.tableName,
|
|
537
|
+
operation: log.operation,
|
|
538
|
+
recordId: log.recordId
|
|
539
|
+
};
|
|
540
|
+
if (log.actorId !== void 0) {
|
|
541
|
+
row.actorId = log.actorId;
|
|
542
|
+
}
|
|
543
|
+
if (log.beforeData !== void 0) {
|
|
544
|
+
row.beforeData = log.beforeData;
|
|
545
|
+
}
|
|
546
|
+
if (log.afterData !== void 0) {
|
|
547
|
+
row.afterData = log.afterData;
|
|
548
|
+
}
|
|
549
|
+
if (log.diff !== void 0) {
|
|
550
|
+
row.diff = log.diff;
|
|
551
|
+
}
|
|
552
|
+
if (log.label !== void 0) {
|
|
553
|
+
row.label = log.label;
|
|
554
|
+
}
|
|
555
|
+
if (log.description !== void 0) {
|
|
556
|
+
row.description = log.description;
|
|
557
|
+
}
|
|
558
|
+
if (log.severity !== void 0) {
|
|
559
|
+
row.severity = log.severity;
|
|
560
|
+
}
|
|
561
|
+
if (log.compliance !== void 0) {
|
|
562
|
+
row.compliance = log.compliance;
|
|
563
|
+
}
|
|
564
|
+
if (log.notify !== void 0) {
|
|
565
|
+
row.notify = log.notify;
|
|
566
|
+
}
|
|
567
|
+
if (log.reason !== void 0) {
|
|
568
|
+
row.reason = log.reason;
|
|
569
|
+
}
|
|
570
|
+
if (log.metadata !== void 0) {
|
|
571
|
+
row.metadata = log.metadata;
|
|
572
|
+
}
|
|
573
|
+
if (log.redactedFields !== void 0) {
|
|
574
|
+
row.redactedFields = log.redactedFields;
|
|
575
|
+
}
|
|
576
|
+
return row;
|
|
577
|
+
}
|
|
578
|
+
function sqliteRowToAuditLog(row) {
|
|
579
|
+
if (!isAuditOperation2(row.operation)) {
|
|
580
|
+
throw new Error(
|
|
581
|
+
`Invalid audit operation: "${row.operation}". Expected one of: INSERT, UPDATE, DELETE`
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
const log = {
|
|
585
|
+
id: row.id,
|
|
586
|
+
timestamp: row.timestamp,
|
|
587
|
+
tableName: row.tableName,
|
|
588
|
+
operation: row.operation,
|
|
589
|
+
recordId: row.recordId
|
|
590
|
+
};
|
|
591
|
+
if (row.actorId !== null) {
|
|
592
|
+
log.actorId = row.actorId;
|
|
593
|
+
}
|
|
594
|
+
if (row.beforeData !== null) {
|
|
595
|
+
log.beforeData = row.beforeData;
|
|
596
|
+
}
|
|
597
|
+
if (row.afterData !== null) {
|
|
598
|
+
log.afterData = row.afterData;
|
|
599
|
+
}
|
|
600
|
+
if (row.diff !== null) {
|
|
601
|
+
log.diff = row.diff;
|
|
602
|
+
}
|
|
603
|
+
if (row.label !== null) {
|
|
604
|
+
log.label = row.label;
|
|
605
|
+
}
|
|
606
|
+
if (row.description !== null) {
|
|
607
|
+
log.description = row.description;
|
|
608
|
+
}
|
|
609
|
+
if (row.severity !== null && row.severity !== void 0) {
|
|
610
|
+
if (!isAuditSeverity2(row.severity)) {
|
|
611
|
+
throw new Error(
|
|
612
|
+
`Invalid audit severity: "${row.severity}". Expected one of: low, medium, high, critical`
|
|
613
|
+
);
|
|
614
|
+
}
|
|
615
|
+
log.severity = row.severity;
|
|
616
|
+
}
|
|
617
|
+
if (row.compliance !== null) {
|
|
618
|
+
log.compliance = row.compliance;
|
|
619
|
+
}
|
|
620
|
+
if (row.notify !== null) {
|
|
621
|
+
log.notify = row.notify;
|
|
622
|
+
}
|
|
623
|
+
if (row.reason !== null) {
|
|
624
|
+
log.reason = row.reason;
|
|
625
|
+
}
|
|
626
|
+
if (row.metadata !== null) {
|
|
627
|
+
log.metadata = row.metadata;
|
|
628
|
+
}
|
|
629
|
+
if (row.redactedFields !== null) {
|
|
630
|
+
log.redactedFields = row.redactedFields;
|
|
631
|
+
}
|
|
632
|
+
return log;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// src/sqlite-query.ts
|
|
636
|
+
var import_audit_core2 = require("@usebetterdev/audit-core");
|
|
470
637
|
var import_drizzle_orm3 = require("drizzle-orm");
|
|
638
|
+
function escapeLikePattern2(input) {
|
|
639
|
+
return input.replace(/[%_\\]/g, "\\$&");
|
|
640
|
+
}
|
|
641
|
+
function resolveTimeFilter2(filter) {
|
|
642
|
+
if ("date" in filter && filter.date !== void 0) {
|
|
643
|
+
return filter.date;
|
|
644
|
+
}
|
|
645
|
+
if ("duration" in filter && filter.duration !== void 0) {
|
|
646
|
+
return (0, import_audit_core2.parseDuration)(filter.duration);
|
|
647
|
+
}
|
|
648
|
+
throw new Error("TimeFilter must have either date or duration");
|
|
649
|
+
}
|
|
650
|
+
function buildSqliteWhereConditions(filters) {
|
|
651
|
+
const conditions = [];
|
|
652
|
+
if (filters.resource !== void 0) {
|
|
653
|
+
conditions.push((0, import_drizzle_orm3.eq)(sqliteAuditLogs.tableName, filters.resource.tableName));
|
|
654
|
+
if (filters.resource.recordId !== void 0) {
|
|
655
|
+
conditions.push((0, import_drizzle_orm3.eq)(sqliteAuditLogs.recordId, filters.resource.recordId));
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
if (filters.actorIds !== void 0 && filters.actorIds.length > 0) {
|
|
659
|
+
if (filters.actorIds.length === 1) {
|
|
660
|
+
conditions.push((0, import_drizzle_orm3.eq)(sqliteAuditLogs.actorId, filters.actorIds[0]));
|
|
661
|
+
} else {
|
|
662
|
+
conditions.push((0, import_drizzle_orm3.inArray)(sqliteAuditLogs.actorId, filters.actorIds));
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (filters.severities !== void 0 && filters.severities.length > 0) {
|
|
666
|
+
if (filters.severities.length === 1) {
|
|
667
|
+
conditions.push((0, import_drizzle_orm3.eq)(sqliteAuditLogs.severity, filters.severities[0]));
|
|
668
|
+
} else {
|
|
669
|
+
conditions.push((0, import_drizzle_orm3.inArray)(sqliteAuditLogs.severity, filters.severities));
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
if (filters.operations !== void 0 && filters.operations.length > 0) {
|
|
673
|
+
if (filters.operations.length === 1) {
|
|
674
|
+
conditions.push((0, import_drizzle_orm3.eq)(sqliteAuditLogs.operation, filters.operations[0]));
|
|
675
|
+
} else {
|
|
676
|
+
conditions.push((0, import_drizzle_orm3.inArray)(sqliteAuditLogs.operation, filters.operations));
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
if (filters.since !== void 0) {
|
|
680
|
+
conditions.push((0, import_drizzle_orm3.gte)(sqliteAuditLogs.timestamp, resolveTimeFilter2(filters.since)));
|
|
681
|
+
}
|
|
682
|
+
if (filters.until !== void 0) {
|
|
683
|
+
conditions.push((0, import_drizzle_orm3.lte)(sqliteAuditLogs.timestamp, resolveTimeFilter2(filters.until)));
|
|
684
|
+
}
|
|
685
|
+
if (filters.searchText !== void 0 && filters.searchText.length > 0) {
|
|
686
|
+
const escaped = escapeLikePattern2(filters.searchText);
|
|
687
|
+
const pattern = `%${escaped}%`;
|
|
688
|
+
const searchCondition = (0, import_drizzle_orm3.or)(
|
|
689
|
+
(0, import_drizzle_orm3.like)(sqliteAuditLogs.label, pattern),
|
|
690
|
+
(0, import_drizzle_orm3.like)(sqliteAuditLogs.description, pattern)
|
|
691
|
+
);
|
|
692
|
+
if (searchCondition !== void 0) {
|
|
693
|
+
conditions.push(searchCondition);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
if (filters.compliance !== void 0 && filters.compliance.length > 0) {
|
|
697
|
+
for (const tag of filters.compliance) {
|
|
698
|
+
conditions.push(
|
|
699
|
+
import_drizzle_orm3.sql`EXISTS (SELECT 1 FROM json_each(${sqliteAuditLogs.compliance}) WHERE value = ${tag})`
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
if (conditions.length === 0) {
|
|
704
|
+
return void 0;
|
|
705
|
+
}
|
|
706
|
+
return (0, import_drizzle_orm3.and)(...conditions);
|
|
707
|
+
}
|
|
708
|
+
function buildSqliteCursorCondition(cursor, sortOrder) {
|
|
709
|
+
const decoded = decodeSqliteCursor(cursor);
|
|
710
|
+
const tsCompare = sortOrder === "asc" ? import_drizzle_orm3.gt : import_drizzle_orm3.lt;
|
|
711
|
+
const idCompare = sortOrder === "asc" ? import_drizzle_orm3.gt : import_drizzle_orm3.lt;
|
|
712
|
+
return (0, import_drizzle_orm3.or)(
|
|
713
|
+
tsCompare(sqliteAuditLogs.timestamp, decoded.timestamp),
|
|
714
|
+
(0, import_drizzle_orm3.and)(
|
|
715
|
+
(0, import_drizzle_orm3.eq)(sqliteAuditLogs.timestamp, decoded.timestamp),
|
|
716
|
+
idCompare(sqliteAuditLogs.id, decoded.id)
|
|
717
|
+
)
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
function buildSqliteOrderBy(sortOrder) {
|
|
721
|
+
if (sortOrder === "asc") {
|
|
722
|
+
return [(0, import_drizzle_orm3.asc)(sqliteAuditLogs.timestamp), (0, import_drizzle_orm3.asc)(sqliteAuditLogs.id)];
|
|
723
|
+
}
|
|
724
|
+
return [(0, import_drizzle_orm3.desc)(sqliteAuditLogs.timestamp), (0, import_drizzle_orm3.desc)(sqliteAuditLogs.id)];
|
|
725
|
+
}
|
|
726
|
+
function encodeSqliteCursor(timestamp2, id) {
|
|
727
|
+
const payload = JSON.stringify({ t: timestamp2.toISOString(), i: id });
|
|
728
|
+
return btoa(payload);
|
|
729
|
+
}
|
|
730
|
+
var UUID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
731
|
+
function decodeSqliteCursor(cursor) {
|
|
732
|
+
let parsed;
|
|
733
|
+
try {
|
|
734
|
+
parsed = JSON.parse(atob(cursor));
|
|
735
|
+
} catch {
|
|
736
|
+
throw new Error("Invalid cursor: failed to decode");
|
|
737
|
+
}
|
|
738
|
+
if (typeof parsed !== "object" || parsed === null || !("t" in parsed) || !("i" in parsed)) {
|
|
739
|
+
throw new Error("Invalid cursor: missing required fields");
|
|
740
|
+
}
|
|
741
|
+
const { t, i } = parsed;
|
|
742
|
+
if (typeof t !== "string" || typeof i !== "string") {
|
|
743
|
+
throw new Error("Invalid cursor: fields must be strings");
|
|
744
|
+
}
|
|
745
|
+
const timestamp2 = new Date(t);
|
|
746
|
+
if (isNaN(timestamp2.getTime())) {
|
|
747
|
+
throw new Error("Invalid cursor: invalid timestamp");
|
|
748
|
+
}
|
|
749
|
+
if (!UUID_PATTERN2.test(i)) {
|
|
750
|
+
throw new Error("Invalid cursor: id must be a valid UUID");
|
|
751
|
+
}
|
|
752
|
+
return { timestamp: timestamp2, id: i };
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// src/sqlite-adapter.ts
|
|
756
|
+
var DEFAULT_LIMIT2 = 50;
|
|
757
|
+
var MAX_LIMIT2 = 250;
|
|
758
|
+
function toCount2(value) {
|
|
759
|
+
if (typeof value === "number") {
|
|
760
|
+
return value;
|
|
761
|
+
}
|
|
762
|
+
if (typeof value === "string") {
|
|
763
|
+
return Number(value);
|
|
764
|
+
}
|
|
765
|
+
return 0;
|
|
766
|
+
}
|
|
767
|
+
function drizzleSqliteAuditAdapter(db) {
|
|
768
|
+
return {
|
|
769
|
+
async writeLog(log) {
|
|
770
|
+
const row = sqliteAuditLogToRow(log);
|
|
771
|
+
await db.insert(sqliteAuditLogs).values(row).execute();
|
|
772
|
+
},
|
|
773
|
+
async queryLogs(spec) {
|
|
774
|
+
const sortOrder = spec.sortOrder ?? "desc";
|
|
775
|
+
const limit = Math.min(spec.limit ?? DEFAULT_LIMIT2, MAX_LIMIT2);
|
|
776
|
+
const whereCondition = buildSqliteWhereConditions(spec.filters);
|
|
777
|
+
const cursorCondition = spec.cursor !== void 0 ? buildSqliteCursorCondition(spec.cursor, sortOrder) : void 0;
|
|
778
|
+
const combined = (0, import_drizzle_orm4.and)(whereCondition, cursorCondition);
|
|
779
|
+
const fetchLimit = limit + 1;
|
|
780
|
+
const orderColumns = buildSqliteOrderBy(sortOrder);
|
|
781
|
+
const query = db.select().from(sqliteAuditLogs).where(combined).orderBy(...orderColumns).limit(fetchLimit);
|
|
782
|
+
const rows = await query;
|
|
783
|
+
const hasNextPage = rows.length > limit;
|
|
784
|
+
const resultRows = hasNextPage ? rows.slice(0, -1) : rows;
|
|
785
|
+
const entries = resultRows.map(sqliteRowToAuditLog);
|
|
786
|
+
const lastRow = resultRows[resultRows.length - 1];
|
|
787
|
+
if (hasNextPage && lastRow !== void 0) {
|
|
788
|
+
return { entries, nextCursor: encodeSqliteCursor(lastRow.timestamp, lastRow.id) };
|
|
789
|
+
}
|
|
790
|
+
return { entries };
|
|
791
|
+
},
|
|
792
|
+
async getLogById(id) {
|
|
793
|
+
const query = db.select().from(sqliteAuditLogs).where((0, import_drizzle_orm4.eq)(sqliteAuditLogs.id, id)).limit(1);
|
|
794
|
+
const rows = await query;
|
|
795
|
+
const row = rows[0];
|
|
796
|
+
if (row === void 0) {
|
|
797
|
+
return null;
|
|
798
|
+
}
|
|
799
|
+
return sqliteRowToAuditLog(row);
|
|
800
|
+
},
|
|
801
|
+
async purgeLogs(options) {
|
|
802
|
+
if (options.tableName !== void 0 && options.tableName.trim().length === 0) {
|
|
803
|
+
throw new Error("purgeLogs: tableName must be a non-empty string when provided");
|
|
804
|
+
}
|
|
805
|
+
const conditions = [(0, import_drizzle_orm4.lt)(sqliteAuditLogs.timestamp, options.before)];
|
|
806
|
+
if (options.tableName !== void 0) {
|
|
807
|
+
conditions.push((0, import_drizzle_orm4.eq)(sqliteAuditLogs.tableName, options.tableName));
|
|
808
|
+
}
|
|
809
|
+
await db.delete(sqliteAuditLogs).where((0, import_drizzle_orm4.and)(...conditions));
|
|
810
|
+
const changesResult = await db.select({ count: import_drizzle_orm4.sql`changes()` }).from(sqliteAuditLogs);
|
|
811
|
+
const deletedCount = changesResult[0] !== void 0 ? toCount2(changesResult[0].count) : 0;
|
|
812
|
+
return { deletedCount };
|
|
813
|
+
},
|
|
814
|
+
async getStats(options) {
|
|
815
|
+
const sinceCondition = options?.since !== void 0 ? (0, import_drizzle_orm4.gte)(sqliteAuditLogs.timestamp, options.since) : void 0;
|
|
816
|
+
const summaryQuery = db.select({
|
|
817
|
+
totalLogs: import_drizzle_orm4.sql`count(*)`,
|
|
818
|
+
tablesAudited: import_drizzle_orm4.sql`count(DISTINCT ${sqliteAuditLogs.tableName})`
|
|
819
|
+
}).from(sqliteAuditLogs).where(sinceCondition);
|
|
820
|
+
const eventsPerDayQuery = db.select({
|
|
821
|
+
date: import_drizzle_orm4.sql`strftime('%Y-%m-%d', ${sqliteAuditLogs.timestamp}, 'unixepoch')`,
|
|
822
|
+
count: import_drizzle_orm4.sql`count(*)`
|
|
823
|
+
}).from(sqliteAuditLogs).where(sinceCondition).groupBy(import_drizzle_orm4.sql`strftime('%Y-%m-%d', ${sqliteAuditLogs.timestamp}, 'unixepoch')`).orderBy(import_drizzle_orm4.sql`strftime('%Y-%m-%d', ${sqliteAuditLogs.timestamp}, 'unixepoch')`).limit(365);
|
|
824
|
+
const topActorsQuery = db.select({
|
|
825
|
+
actorId: sqliteAuditLogs.actorId,
|
|
826
|
+
count: import_drizzle_orm4.sql`count(*)`
|
|
827
|
+
}).from(sqliteAuditLogs).where((0, import_drizzle_orm4.and)(sinceCondition, (0, import_drizzle_orm4.isNotNull)(sqliteAuditLogs.actorId))).groupBy(sqliteAuditLogs.actorId).orderBy((0, import_drizzle_orm4.desc)(import_drizzle_orm4.sql`count(*)`)).limit(10);
|
|
828
|
+
const topTablesQuery = db.select({
|
|
829
|
+
tableName: sqliteAuditLogs.tableName,
|
|
830
|
+
count: import_drizzle_orm4.sql`count(*)`
|
|
831
|
+
}).from(sqliteAuditLogs).where(sinceCondition).groupBy(sqliteAuditLogs.tableName).orderBy((0, import_drizzle_orm4.desc)(import_drizzle_orm4.sql`count(*)`)).limit(10);
|
|
832
|
+
const operationQuery = db.select({
|
|
833
|
+
operation: sqliteAuditLogs.operation,
|
|
834
|
+
count: import_drizzle_orm4.sql`count(*)`
|
|
835
|
+
}).from(sqliteAuditLogs).where(sinceCondition).groupBy(sqliteAuditLogs.operation);
|
|
836
|
+
const severityQuery = db.select({
|
|
837
|
+
severity: sqliteAuditLogs.severity,
|
|
838
|
+
count: import_drizzle_orm4.sql`count(*)`
|
|
839
|
+
}).from(sqliteAuditLogs).where((0, import_drizzle_orm4.and)(sinceCondition, (0, import_drizzle_orm4.isNotNull)(sqliteAuditLogs.severity))).groupBy(sqliteAuditLogs.severity);
|
|
840
|
+
const results = await Promise.all([
|
|
841
|
+
summaryQuery,
|
|
842
|
+
eventsPerDayQuery,
|
|
843
|
+
topActorsQuery,
|
|
844
|
+
topTablesQuery,
|
|
845
|
+
operationQuery,
|
|
846
|
+
severityQuery
|
|
847
|
+
]);
|
|
848
|
+
const [
|
|
849
|
+
summaryRows,
|
|
850
|
+
eventsPerDayRows,
|
|
851
|
+
topActorsRows,
|
|
852
|
+
topTablesRows,
|
|
853
|
+
operationRows,
|
|
854
|
+
severityRows
|
|
855
|
+
] = results;
|
|
856
|
+
return assembleStats2(
|
|
857
|
+
summaryRows,
|
|
858
|
+
eventsPerDayRows,
|
|
859
|
+
topActorsRows,
|
|
860
|
+
topTablesRows,
|
|
861
|
+
operationRows,
|
|
862
|
+
severityRows
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
function assembleStats2(summaryRows, eventsPerDayRows, topActorsRows, topTablesRows, operationRows, severityRows) {
|
|
868
|
+
const summary = summaryRows[0];
|
|
869
|
+
const totalLogs = summary !== void 0 ? toCount2(summary.totalLogs) : 0;
|
|
870
|
+
const tablesAudited = summary !== void 0 ? toCount2(summary.tablesAudited) : 0;
|
|
871
|
+
const eventsPerDay = eventsPerDayRows.map((row) => ({
|
|
872
|
+
date: String(row.date),
|
|
873
|
+
count: toCount2(row.count)
|
|
874
|
+
}));
|
|
875
|
+
const topActors = topActorsRows.map((row) => ({
|
|
876
|
+
actorId: String(row.actorId),
|
|
877
|
+
count: toCount2(row.count)
|
|
878
|
+
}));
|
|
879
|
+
const topTables = topTablesRows.map((row) => ({
|
|
880
|
+
tableName: String(row.tableName),
|
|
881
|
+
count: toCount2(row.count)
|
|
882
|
+
}));
|
|
883
|
+
const operationBreakdown = {};
|
|
884
|
+
for (const row of operationRows) {
|
|
885
|
+
operationBreakdown[String(row.operation)] = toCount2(row.count);
|
|
886
|
+
}
|
|
887
|
+
const severityBreakdown = {};
|
|
888
|
+
for (const row of severityRows) {
|
|
889
|
+
severityBreakdown[String(row.severity)] = toCount2(row.count);
|
|
890
|
+
}
|
|
891
|
+
return {
|
|
892
|
+
totalLogs,
|
|
893
|
+
tablesAudited,
|
|
894
|
+
eventsPerDay,
|
|
895
|
+
topActors,
|
|
896
|
+
topTables,
|
|
897
|
+
operationBreakdown,
|
|
898
|
+
severityBreakdown
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// src/proxy.ts
|
|
903
|
+
var import_drizzle_orm5 = require("drizzle-orm");
|
|
471
904
|
|
|
472
905
|
// src/operation-map.ts
|
|
473
906
|
var OPERATION_MAP = {
|
|
@@ -501,7 +934,7 @@ function withAuditProxy(db, captureLog, options) {
|
|
|
501
934
|
const method = prop;
|
|
502
935
|
const originalMethod = Reflect.get(target, prop, receiver);
|
|
503
936
|
return (table) => {
|
|
504
|
-
const tableName = (0,
|
|
937
|
+
const tableName = (0, import_drizzle_orm5.getTableName)(table);
|
|
505
938
|
const detectedPk = getPrimaryKeyColumnName(table);
|
|
506
939
|
const effectivePk = detectedPk ?? primaryKey;
|
|
507
940
|
const originalBuilder = originalMethod.call(target, table);
|
|
@@ -965,7 +1398,9 @@ async function fireCaptureLog(result, ctx, state) {
|
|
|
965
1398
|
buildWhereConditions,
|
|
966
1399
|
decodeCursor,
|
|
967
1400
|
drizzleAuditAdapter,
|
|
1401
|
+
drizzleSqliteAuditAdapter,
|
|
968
1402
|
encodeCursor,
|
|
1403
|
+
sqliteAuditLogs,
|
|
969
1404
|
withAuditProxy
|
|
970
1405
|
});
|
|
971
1406
|
//# sourceMappingURL=index.cjs.map
|