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