@usebetterdev/audit-core 0.6.0 → 0.7.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 +196 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -1
- package/dist/index.d.ts +121 -1
- package/dist/index.js +182 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.d.cts
CHANGED
|
@@ -452,6 +452,120 @@ declare const AUDIT_LOG_SCHEMA: AuditLogSchema;
|
|
|
452
452
|
*/
|
|
453
453
|
declare function parseDuration(input: string, referenceDate?: Date): Date;
|
|
454
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Encodes a cursor from a timestamp and id.
|
|
457
|
+
* Format: base64(JSON.stringify({ t: iso_string, i: id }))
|
|
458
|
+
*/
|
|
459
|
+
declare function encodeCursor(timestamp: Date, id: string): string;
|
|
460
|
+
/**
|
|
461
|
+
* Decodes an opaque cursor string back to timestamp + id.
|
|
462
|
+
* Throws on invalid input.
|
|
463
|
+
*/
|
|
464
|
+
declare function decodeCursor(cursor: string): {
|
|
465
|
+
timestamp: Date;
|
|
466
|
+
id: string;
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Escapes LIKE/ILIKE wildcard characters so they match literally.
|
|
471
|
+
* Backslash is the default escape character in PostgreSQL and SQLite LIKE patterns.
|
|
472
|
+
*/
|
|
473
|
+
declare function escapeLikePattern(input: string): string;
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Resolves a `TimeFilter` to an absolute `Date`.
|
|
477
|
+
* Absolute dates are returned as-is; duration strings are parsed relative to now.
|
|
478
|
+
*/
|
|
479
|
+
declare function resolveTimeFilter(filter: TimeFilter): Date;
|
|
480
|
+
|
|
481
|
+
/** Column names that support simple equality / IN filtering. */
|
|
482
|
+
type AuditFilterField = "tableName" | "recordId" | "actorId" | "severity" | "operation";
|
|
483
|
+
/**
|
|
484
|
+
* Intermediate representation for a single filter condition.
|
|
485
|
+
*
|
|
486
|
+
* Adapters map each variant to their native expression type
|
|
487
|
+
* (Drizzle `SQL`, Prisma `QueryState` fragments, etc.).
|
|
488
|
+
*/
|
|
489
|
+
type FilterCondition = {
|
|
490
|
+
readonly kind: "eq";
|
|
491
|
+
readonly field: AuditFilterField;
|
|
492
|
+
readonly value: string;
|
|
493
|
+
} | {
|
|
494
|
+
readonly kind: "in";
|
|
495
|
+
readonly field: AuditFilterField;
|
|
496
|
+
readonly values: string[];
|
|
497
|
+
} | {
|
|
498
|
+
readonly kind: "timestampGte";
|
|
499
|
+
readonly value: Date;
|
|
500
|
+
} | {
|
|
501
|
+
readonly kind: "timestampLte";
|
|
502
|
+
readonly value: Date;
|
|
503
|
+
} | {
|
|
504
|
+
readonly kind: "search";
|
|
505
|
+
readonly pattern: string;
|
|
506
|
+
} | {
|
|
507
|
+
readonly kind: "compliance";
|
|
508
|
+
readonly tags: string[];
|
|
509
|
+
} | {
|
|
510
|
+
readonly kind: "cursor";
|
|
511
|
+
readonly timestamp: Date;
|
|
512
|
+
readonly id: string;
|
|
513
|
+
readonly sortOrder: "asc" | "desc";
|
|
514
|
+
};
|
|
515
|
+
interface InterpretFiltersOptions {
|
|
516
|
+
cursor?: {
|
|
517
|
+
timestamp: Date;
|
|
518
|
+
id: string;
|
|
519
|
+
} | undefined;
|
|
520
|
+
sortOrder?: "asc" | "desc" | undefined;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Converts `AuditQueryFilters` + optional cursor into a flat array of
|
|
524
|
+
* `FilterCondition` values. Pure, zero-dep, independently testable.
|
|
525
|
+
*
|
|
526
|
+
* Decision logic (shared across all adapters):
|
|
527
|
+
* - Array filters with 1 element → `eq`, >1 → `in`, 0/undefined → skip
|
|
528
|
+
* - Time filters → resolved to absolute `Date` via `resolveTimeFilter()`
|
|
529
|
+
* - Search text → escaped + wrapped with `%` for LIKE/ILIKE
|
|
530
|
+
* - Compliance tags → passed through (adapter handles JSONB vs json_each)
|
|
531
|
+
* - Cursor → emitted with sort order for adapter-specific comparison
|
|
532
|
+
*/
|
|
533
|
+
declare function interpretFilters(filters: AuditQueryFilters, options?: InterpretFiltersOptions): readonly FilterCondition[];
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Safely converts a count value (number, string, or bigint) to a JavaScript number.
|
|
537
|
+
* Handles PostgreSQL bigint-as-string, Prisma BigInt, and SQLite numeric returns.
|
|
538
|
+
*/
|
|
539
|
+
declare function toCount(value: unknown): number;
|
|
540
|
+
/**
|
|
541
|
+
* Assembles raw query result arrays into an `AuditStats` object.
|
|
542
|
+
* Works for both Date objects (PostgreSQL) and strings (SQLite, Prisma raw).
|
|
543
|
+
*/
|
|
544
|
+
declare function assembleStats(summaryRows: Array<{
|
|
545
|
+
totalLogs: unknown;
|
|
546
|
+
tablesAudited: unknown;
|
|
547
|
+
}>, eventsPerDayRows: Array<{
|
|
548
|
+
date: unknown;
|
|
549
|
+
count: unknown;
|
|
550
|
+
}>, topActorsRows: Array<{
|
|
551
|
+
actorId: unknown;
|
|
552
|
+
count: unknown;
|
|
553
|
+
}>, topTablesRows: Array<{
|
|
554
|
+
tableName: unknown;
|
|
555
|
+
count: unknown;
|
|
556
|
+
}>, operationRows: Array<{
|
|
557
|
+
operation: unknown;
|
|
558
|
+
count: unknown;
|
|
559
|
+
}>, severityRows: Array<{
|
|
560
|
+
severity: unknown;
|
|
561
|
+
count: unknown;
|
|
562
|
+
}>): AuditStats;
|
|
563
|
+
|
|
564
|
+
declare const VALID_OPERATIONS: ReadonlySet<string>;
|
|
565
|
+
declare const VALID_SEVERITIES: ReadonlySet<string>;
|
|
566
|
+
declare function isAuditOperation(value: string): value is AuditOperation;
|
|
567
|
+
declare function isAuditSeverity(value: string): value is AuditSeverity;
|
|
568
|
+
|
|
455
569
|
/**
|
|
456
570
|
* Core export engine. Fetches rows in cursor-paginated batches and writes
|
|
457
571
|
* them to the sink as CSV or JSON. Memory stays flat regardless of total rows.
|
|
@@ -585,6 +699,12 @@ declare function fromCookie(cookieName: string): ValueExtractor;
|
|
|
585
699
|
* @param headerName - Header name (case-insensitive per the Web API)
|
|
586
700
|
*/
|
|
587
701
|
declare function fromHeader(headerName: string): ValueExtractor;
|
|
702
|
+
/** Default extractor: reads `sub` from `Authorization: Bearer <jwt>` as actor. */
|
|
703
|
+
declare const defaultExtractor: ContextExtractor;
|
|
704
|
+
/**
|
|
705
|
+
* Runs an extractor safely, catching errors and returning undefined on failure.
|
|
706
|
+
*/
|
|
707
|
+
declare function safeExtract(extractor: ValueExtractor | undefined, request: Request, onError: ((error: unknown) => void) | undefined): Promise<string | undefined>;
|
|
588
708
|
/**
|
|
589
709
|
* Shared middleware handler used by all framework adapters.
|
|
590
710
|
*
|
|
@@ -597,4 +717,4 @@ declare function fromHeader(headerName: string): ValueExtractor;
|
|
|
597
717
|
*/
|
|
598
718
|
declare function handleMiddleware(extractor: ContextExtractor, request: Request, next: () => Promise<void>, options?: MiddlewareHandlerOptions): Promise<void>;
|
|
599
719
|
|
|
600
|
-
export { AUDIT_LOG_SCHEMA, type AfterLogHook, type AuditApi, type AuditContext, type AuditDatabaseAdapter, type AuditLog, type AuditLogColumnName, type AuditLogSchema, type AuditOperation, AuditQueryBuilder, type AuditQueryFilters, type AuditQueryResult, type AuditQuerySpec, type AuditSeverity, type AuditStats, type BeforeLogHook, type BetterAuditConfig, type BetterAuditInstance, type CaptureLogInput, type ColumnDefinition, type ColumnType, type ConsoleQueryFilters, type ConsoleQueryResult, type ContextExtractor, type EnrichmentConfig, type EnrichmentDescriptionContext, type EnrichmentSummary, type ExportOptions, type ExportResponseOptions, type ExportResult, type MiddlewareHandlerOptions, type QueryExecutor, type ResourceFilter, type TimeFilter, type ValueExtractor, betterAudit, createAuditApi, createAuditConsoleEndpoints, createExportResponse, fromBearerToken, fromCookie, fromHeader, getAuditContext, handleMiddleware, mergeAuditContext, normalizeInput, parseDuration, runExport, runWithAuditContext };
|
|
720
|
+
export { AUDIT_LOG_SCHEMA, type AfterLogHook, type AuditApi, type AuditContext, type AuditDatabaseAdapter, type AuditFilterField, type AuditLog, type AuditLogColumnName, type AuditLogSchema, type AuditOperation, AuditQueryBuilder, type AuditQueryFilters, type AuditQueryResult, type AuditQuerySpec, type AuditSeverity, type AuditStats, type BeforeLogHook, type BetterAuditConfig, type BetterAuditInstance, type CaptureLogInput, type ColumnDefinition, type ColumnType, type ConsoleQueryFilters, type ConsoleQueryResult, type ContextExtractor, type EnrichmentConfig, type EnrichmentDescriptionContext, type EnrichmentSummary, type ExportOptions, type ExportResponseOptions, type ExportResult, type FilterCondition, type InterpretFiltersOptions, type MiddlewareHandlerOptions, type QueryExecutor, type ResourceFilter, type TimeFilter, VALID_OPERATIONS, VALID_SEVERITIES, type ValueExtractor, assembleStats, betterAudit, createAuditApi, createAuditConsoleEndpoints, createExportResponse, decodeCursor, defaultExtractor, encodeCursor, escapeLikePattern, fromBearerToken, fromCookie, fromHeader, getAuditContext, handleMiddleware, interpretFilters, isAuditOperation, isAuditSeverity, mergeAuditContext, normalizeInput, parseDuration, resolveTimeFilter, runExport, runWithAuditContext, safeExtract, toCount };
|
package/dist/index.d.ts
CHANGED
|
@@ -452,6 +452,120 @@ declare const AUDIT_LOG_SCHEMA: AuditLogSchema;
|
|
|
452
452
|
*/
|
|
453
453
|
declare function parseDuration(input: string, referenceDate?: Date): Date;
|
|
454
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Encodes a cursor from a timestamp and id.
|
|
457
|
+
* Format: base64(JSON.stringify({ t: iso_string, i: id }))
|
|
458
|
+
*/
|
|
459
|
+
declare function encodeCursor(timestamp: Date, id: string): string;
|
|
460
|
+
/**
|
|
461
|
+
* Decodes an opaque cursor string back to timestamp + id.
|
|
462
|
+
* Throws on invalid input.
|
|
463
|
+
*/
|
|
464
|
+
declare function decodeCursor(cursor: string): {
|
|
465
|
+
timestamp: Date;
|
|
466
|
+
id: string;
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Escapes LIKE/ILIKE wildcard characters so they match literally.
|
|
471
|
+
* Backslash is the default escape character in PostgreSQL and SQLite LIKE patterns.
|
|
472
|
+
*/
|
|
473
|
+
declare function escapeLikePattern(input: string): string;
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Resolves a `TimeFilter` to an absolute `Date`.
|
|
477
|
+
* Absolute dates are returned as-is; duration strings are parsed relative to now.
|
|
478
|
+
*/
|
|
479
|
+
declare function resolveTimeFilter(filter: TimeFilter): Date;
|
|
480
|
+
|
|
481
|
+
/** Column names that support simple equality / IN filtering. */
|
|
482
|
+
type AuditFilterField = "tableName" | "recordId" | "actorId" | "severity" | "operation";
|
|
483
|
+
/**
|
|
484
|
+
* Intermediate representation for a single filter condition.
|
|
485
|
+
*
|
|
486
|
+
* Adapters map each variant to their native expression type
|
|
487
|
+
* (Drizzle `SQL`, Prisma `QueryState` fragments, etc.).
|
|
488
|
+
*/
|
|
489
|
+
type FilterCondition = {
|
|
490
|
+
readonly kind: "eq";
|
|
491
|
+
readonly field: AuditFilterField;
|
|
492
|
+
readonly value: string;
|
|
493
|
+
} | {
|
|
494
|
+
readonly kind: "in";
|
|
495
|
+
readonly field: AuditFilterField;
|
|
496
|
+
readonly values: string[];
|
|
497
|
+
} | {
|
|
498
|
+
readonly kind: "timestampGte";
|
|
499
|
+
readonly value: Date;
|
|
500
|
+
} | {
|
|
501
|
+
readonly kind: "timestampLte";
|
|
502
|
+
readonly value: Date;
|
|
503
|
+
} | {
|
|
504
|
+
readonly kind: "search";
|
|
505
|
+
readonly pattern: string;
|
|
506
|
+
} | {
|
|
507
|
+
readonly kind: "compliance";
|
|
508
|
+
readonly tags: string[];
|
|
509
|
+
} | {
|
|
510
|
+
readonly kind: "cursor";
|
|
511
|
+
readonly timestamp: Date;
|
|
512
|
+
readonly id: string;
|
|
513
|
+
readonly sortOrder: "asc" | "desc";
|
|
514
|
+
};
|
|
515
|
+
interface InterpretFiltersOptions {
|
|
516
|
+
cursor?: {
|
|
517
|
+
timestamp: Date;
|
|
518
|
+
id: string;
|
|
519
|
+
} | undefined;
|
|
520
|
+
sortOrder?: "asc" | "desc" | undefined;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Converts `AuditQueryFilters` + optional cursor into a flat array of
|
|
524
|
+
* `FilterCondition` values. Pure, zero-dep, independently testable.
|
|
525
|
+
*
|
|
526
|
+
* Decision logic (shared across all adapters):
|
|
527
|
+
* - Array filters with 1 element → `eq`, >1 → `in`, 0/undefined → skip
|
|
528
|
+
* - Time filters → resolved to absolute `Date` via `resolveTimeFilter()`
|
|
529
|
+
* - Search text → escaped + wrapped with `%` for LIKE/ILIKE
|
|
530
|
+
* - Compliance tags → passed through (adapter handles JSONB vs json_each)
|
|
531
|
+
* - Cursor → emitted with sort order for adapter-specific comparison
|
|
532
|
+
*/
|
|
533
|
+
declare function interpretFilters(filters: AuditQueryFilters, options?: InterpretFiltersOptions): readonly FilterCondition[];
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Safely converts a count value (number, string, or bigint) to a JavaScript number.
|
|
537
|
+
* Handles PostgreSQL bigint-as-string, Prisma BigInt, and SQLite numeric returns.
|
|
538
|
+
*/
|
|
539
|
+
declare function toCount(value: unknown): number;
|
|
540
|
+
/**
|
|
541
|
+
* Assembles raw query result arrays into an `AuditStats` object.
|
|
542
|
+
* Works for both Date objects (PostgreSQL) and strings (SQLite, Prisma raw).
|
|
543
|
+
*/
|
|
544
|
+
declare function assembleStats(summaryRows: Array<{
|
|
545
|
+
totalLogs: unknown;
|
|
546
|
+
tablesAudited: unknown;
|
|
547
|
+
}>, eventsPerDayRows: Array<{
|
|
548
|
+
date: unknown;
|
|
549
|
+
count: unknown;
|
|
550
|
+
}>, topActorsRows: Array<{
|
|
551
|
+
actorId: unknown;
|
|
552
|
+
count: unknown;
|
|
553
|
+
}>, topTablesRows: Array<{
|
|
554
|
+
tableName: unknown;
|
|
555
|
+
count: unknown;
|
|
556
|
+
}>, operationRows: Array<{
|
|
557
|
+
operation: unknown;
|
|
558
|
+
count: unknown;
|
|
559
|
+
}>, severityRows: Array<{
|
|
560
|
+
severity: unknown;
|
|
561
|
+
count: unknown;
|
|
562
|
+
}>): AuditStats;
|
|
563
|
+
|
|
564
|
+
declare const VALID_OPERATIONS: ReadonlySet<string>;
|
|
565
|
+
declare const VALID_SEVERITIES: ReadonlySet<string>;
|
|
566
|
+
declare function isAuditOperation(value: string): value is AuditOperation;
|
|
567
|
+
declare function isAuditSeverity(value: string): value is AuditSeverity;
|
|
568
|
+
|
|
455
569
|
/**
|
|
456
570
|
* Core export engine. Fetches rows in cursor-paginated batches and writes
|
|
457
571
|
* them to the sink as CSV or JSON. Memory stays flat regardless of total rows.
|
|
@@ -585,6 +699,12 @@ declare function fromCookie(cookieName: string): ValueExtractor;
|
|
|
585
699
|
* @param headerName - Header name (case-insensitive per the Web API)
|
|
586
700
|
*/
|
|
587
701
|
declare function fromHeader(headerName: string): ValueExtractor;
|
|
702
|
+
/** Default extractor: reads `sub` from `Authorization: Bearer <jwt>` as actor. */
|
|
703
|
+
declare const defaultExtractor: ContextExtractor;
|
|
704
|
+
/**
|
|
705
|
+
* Runs an extractor safely, catching errors and returning undefined on failure.
|
|
706
|
+
*/
|
|
707
|
+
declare function safeExtract(extractor: ValueExtractor | undefined, request: Request, onError: ((error: unknown) => void) | undefined): Promise<string | undefined>;
|
|
588
708
|
/**
|
|
589
709
|
* Shared middleware handler used by all framework adapters.
|
|
590
710
|
*
|
|
@@ -597,4 +717,4 @@ declare function fromHeader(headerName: string): ValueExtractor;
|
|
|
597
717
|
*/
|
|
598
718
|
declare function handleMiddleware(extractor: ContextExtractor, request: Request, next: () => Promise<void>, options?: MiddlewareHandlerOptions): Promise<void>;
|
|
599
719
|
|
|
600
|
-
export { AUDIT_LOG_SCHEMA, type AfterLogHook, type AuditApi, type AuditContext, type AuditDatabaseAdapter, type AuditLog, type AuditLogColumnName, type AuditLogSchema, type AuditOperation, AuditQueryBuilder, type AuditQueryFilters, type AuditQueryResult, type AuditQuerySpec, type AuditSeverity, type AuditStats, type BeforeLogHook, type BetterAuditConfig, type BetterAuditInstance, type CaptureLogInput, type ColumnDefinition, type ColumnType, type ConsoleQueryFilters, type ConsoleQueryResult, type ContextExtractor, type EnrichmentConfig, type EnrichmentDescriptionContext, type EnrichmentSummary, type ExportOptions, type ExportResponseOptions, type ExportResult, type MiddlewareHandlerOptions, type QueryExecutor, type ResourceFilter, type TimeFilter, type ValueExtractor, betterAudit, createAuditApi, createAuditConsoleEndpoints, createExportResponse, fromBearerToken, fromCookie, fromHeader, getAuditContext, handleMiddleware, mergeAuditContext, normalizeInput, parseDuration, runExport, runWithAuditContext };
|
|
720
|
+
export { AUDIT_LOG_SCHEMA, type AfterLogHook, type AuditApi, type AuditContext, type AuditDatabaseAdapter, type AuditFilterField, type AuditLog, type AuditLogColumnName, type AuditLogSchema, type AuditOperation, AuditQueryBuilder, type AuditQueryFilters, type AuditQueryResult, type AuditQuerySpec, type AuditSeverity, type AuditStats, type BeforeLogHook, type BetterAuditConfig, type BetterAuditInstance, type CaptureLogInput, type ColumnDefinition, type ColumnType, type ConsoleQueryFilters, type ConsoleQueryResult, type ContextExtractor, type EnrichmentConfig, type EnrichmentDescriptionContext, type EnrichmentSummary, type ExportOptions, type ExportResponseOptions, type ExportResult, type FilterCondition, type InterpretFiltersOptions, type MiddlewareHandlerOptions, type QueryExecutor, type ResourceFilter, type TimeFilter, VALID_OPERATIONS, VALID_SEVERITIES, type ValueExtractor, assembleStats, betterAudit, createAuditApi, createAuditConsoleEndpoints, createExportResponse, decodeCursor, defaultExtractor, encodeCursor, escapeLikePattern, fromBearerToken, fromCookie, fromHeader, getAuditContext, handleMiddleware, interpretFilters, isAuditOperation, isAuditSeverity, mergeAuditContext, normalizeInput, parseDuration, resolveTimeFilter, runExport, runWithAuditContext, safeExtract, toCount };
|
package/dist/index.js
CHANGED
|
@@ -1468,6 +1468,171 @@ var AUDIT_LOG_SCHEMA = {
|
|
|
1468
1468
|
}
|
|
1469
1469
|
};
|
|
1470
1470
|
|
|
1471
|
+
// src/cursor.ts
|
|
1472
|
+
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
1473
|
+
function encodeCursor(timestamp, id) {
|
|
1474
|
+
const payload = JSON.stringify({ t: timestamp.toISOString(), i: id });
|
|
1475
|
+
return btoa(payload);
|
|
1476
|
+
}
|
|
1477
|
+
function decodeCursor(cursor) {
|
|
1478
|
+
let parsed;
|
|
1479
|
+
try {
|
|
1480
|
+
parsed = JSON.parse(atob(cursor));
|
|
1481
|
+
} catch {
|
|
1482
|
+
throw new Error("Invalid cursor: failed to decode");
|
|
1483
|
+
}
|
|
1484
|
+
if (typeof parsed !== "object" || parsed === null || !("t" in parsed) || !("i" in parsed)) {
|
|
1485
|
+
throw new Error("Invalid cursor: missing required fields");
|
|
1486
|
+
}
|
|
1487
|
+
const record = parsed;
|
|
1488
|
+
const t = record["t"];
|
|
1489
|
+
const i = record["i"];
|
|
1490
|
+
if (typeof t !== "string" || typeof i !== "string") {
|
|
1491
|
+
throw new Error("Invalid cursor: fields must be strings");
|
|
1492
|
+
}
|
|
1493
|
+
const timestamp = new Date(t);
|
|
1494
|
+
if (isNaN(timestamp.getTime())) {
|
|
1495
|
+
throw new Error("Invalid cursor: invalid timestamp");
|
|
1496
|
+
}
|
|
1497
|
+
if (!UUID_PATTERN.test(i)) {
|
|
1498
|
+
throw new Error("Invalid cursor: id must be a valid UUID");
|
|
1499
|
+
}
|
|
1500
|
+
return { timestamp, id: i };
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
// src/escape.ts
|
|
1504
|
+
function escapeLikePattern(input) {
|
|
1505
|
+
return input.replace(/[%_\\]/g, "\\$&");
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
// src/time-filter.ts
|
|
1509
|
+
function resolveTimeFilter(filter) {
|
|
1510
|
+
if ("date" in filter && filter.date !== void 0) {
|
|
1511
|
+
return filter.date;
|
|
1512
|
+
}
|
|
1513
|
+
if ("duration" in filter && filter.duration !== void 0) {
|
|
1514
|
+
return parseDuration(filter.duration);
|
|
1515
|
+
}
|
|
1516
|
+
throw new Error("TimeFilter must have either date or duration");
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
// src/filter-builder.ts
|
|
1520
|
+
function interpretFilters(filters, options) {
|
|
1521
|
+
const conditions = [];
|
|
1522
|
+
if (filters.resource !== void 0) {
|
|
1523
|
+
conditions.push({ kind: "eq", field: "tableName", value: filters.resource.tableName });
|
|
1524
|
+
if (filters.resource.recordId !== void 0) {
|
|
1525
|
+
conditions.push({ kind: "eq", field: "recordId", value: filters.resource.recordId });
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
pushArrayFilter(conditions, "actorId", filters.actorIds);
|
|
1529
|
+
pushArrayFilter(conditions, "severity", filters.severities);
|
|
1530
|
+
pushArrayFilter(conditions, "operation", filters.operations);
|
|
1531
|
+
if (filters.since !== void 0) {
|
|
1532
|
+
conditions.push({ kind: "timestampGte", value: resolveTimeFilter(filters.since) });
|
|
1533
|
+
}
|
|
1534
|
+
if (filters.until !== void 0) {
|
|
1535
|
+
conditions.push({ kind: "timestampLte", value: resolveTimeFilter(filters.until) });
|
|
1536
|
+
}
|
|
1537
|
+
if (filters.searchText !== void 0 && filters.searchText.length > 0) {
|
|
1538
|
+
const escaped = escapeLikePattern(filters.searchText);
|
|
1539
|
+
conditions.push({ kind: "search", pattern: `%${escaped}%` });
|
|
1540
|
+
}
|
|
1541
|
+
if (filters.compliance !== void 0 && filters.compliance.length > 0) {
|
|
1542
|
+
conditions.push({ kind: "compliance", tags: [...filters.compliance] });
|
|
1543
|
+
}
|
|
1544
|
+
if (options?.cursor !== void 0) {
|
|
1545
|
+
conditions.push({
|
|
1546
|
+
kind: "cursor",
|
|
1547
|
+
timestamp: options.cursor.timestamp,
|
|
1548
|
+
id: options.cursor.id,
|
|
1549
|
+
sortOrder: options.sortOrder ?? "desc"
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
return conditions;
|
|
1553
|
+
}
|
|
1554
|
+
function pushArrayFilter(conditions, field, values) {
|
|
1555
|
+
if (values === void 0 || values.length === 0) {
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
if (values.length === 1) {
|
|
1559
|
+
const first = values[0];
|
|
1560
|
+
if (first !== void 0) {
|
|
1561
|
+
conditions.push({ kind: "eq", field, value: first });
|
|
1562
|
+
}
|
|
1563
|
+
} else {
|
|
1564
|
+
conditions.push({ kind: "in", field, values: [...values] });
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
// src/stats.ts
|
|
1569
|
+
function toCount(value) {
|
|
1570
|
+
if (typeof value === "number") {
|
|
1571
|
+
return value;
|
|
1572
|
+
}
|
|
1573
|
+
if (typeof value === "string") {
|
|
1574
|
+
const n = Number(value);
|
|
1575
|
+
return Number.isNaN(n) ? 0 : n;
|
|
1576
|
+
}
|
|
1577
|
+
if (typeof value === "bigint") {
|
|
1578
|
+
return Number(value);
|
|
1579
|
+
}
|
|
1580
|
+
return 0;
|
|
1581
|
+
}
|
|
1582
|
+
function assembleStats(summaryRows, eventsPerDayRows, topActorsRows, topTablesRows, operationRows, severityRows) {
|
|
1583
|
+
const summary = summaryRows[0];
|
|
1584
|
+
const totalLogs = summary !== void 0 ? toCount(summary.totalLogs) : 0;
|
|
1585
|
+
const tablesAudited = summary !== void 0 ? toCount(summary.tablesAudited) : 0;
|
|
1586
|
+
const eventsPerDay = eventsPerDayRows.map((row) => ({
|
|
1587
|
+
date: row.date instanceof Date ? row.date.toISOString().split("T")[0] ?? "" : String(row.date),
|
|
1588
|
+
count: toCount(row.count)
|
|
1589
|
+
}));
|
|
1590
|
+
const topActors = topActorsRows.map((row) => ({
|
|
1591
|
+
actorId: String(row.actorId),
|
|
1592
|
+
count: toCount(row.count)
|
|
1593
|
+
}));
|
|
1594
|
+
const topTables = topTablesRows.map((row) => ({
|
|
1595
|
+
tableName: String(row.tableName),
|
|
1596
|
+
count: toCount(row.count)
|
|
1597
|
+
}));
|
|
1598
|
+
const operationBreakdown = {};
|
|
1599
|
+
for (const row of operationRows) {
|
|
1600
|
+
operationBreakdown[String(row.operation)] = toCount(row.count);
|
|
1601
|
+
}
|
|
1602
|
+
const severityBreakdown = {};
|
|
1603
|
+
for (const row of severityRows) {
|
|
1604
|
+
severityBreakdown[String(row.severity)] = toCount(row.count);
|
|
1605
|
+
}
|
|
1606
|
+
return {
|
|
1607
|
+
totalLogs,
|
|
1608
|
+
tablesAudited,
|
|
1609
|
+
eventsPerDay,
|
|
1610
|
+
topActors,
|
|
1611
|
+
topTables,
|
|
1612
|
+
operationBreakdown,
|
|
1613
|
+
severityBreakdown
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
// src/validation.ts
|
|
1618
|
+
var VALID_OPERATIONS2 = /* @__PURE__ */ new Set([
|
|
1619
|
+
"INSERT",
|
|
1620
|
+
"UPDATE",
|
|
1621
|
+
"DELETE"
|
|
1622
|
+
]);
|
|
1623
|
+
var VALID_SEVERITIES2 = /* @__PURE__ */ new Set([
|
|
1624
|
+
"low",
|
|
1625
|
+
"medium",
|
|
1626
|
+
"high",
|
|
1627
|
+
"critical"
|
|
1628
|
+
]);
|
|
1629
|
+
function isAuditOperation(value) {
|
|
1630
|
+
return VALID_OPERATIONS2.has(value);
|
|
1631
|
+
}
|
|
1632
|
+
function isAuditSeverity(value) {
|
|
1633
|
+
return VALID_SEVERITIES2.has(value);
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1471
1636
|
// src/context-extractor.ts
|
|
1472
1637
|
function decodeJwtPayload(token) {
|
|
1473
1638
|
try {
|
|
@@ -1545,6 +1710,9 @@ function fromHeader(headerName) {
|
|
|
1545
1710
|
return value.trim();
|
|
1546
1711
|
};
|
|
1547
1712
|
}
|
|
1713
|
+
var defaultExtractor = {
|
|
1714
|
+
actor: fromBearerToken("sub")
|
|
1715
|
+
};
|
|
1548
1716
|
async function safeExtract(extractor, request, onError) {
|
|
1549
1717
|
if (!extractor) {
|
|
1550
1718
|
return void 0;
|
|
@@ -1570,19 +1738,32 @@ async function handleMiddleware(extractor, request, next, options = {}) {
|
|
|
1570
1738
|
export {
|
|
1571
1739
|
AUDIT_LOG_SCHEMA,
|
|
1572
1740
|
AuditQueryBuilder,
|
|
1741
|
+
VALID_OPERATIONS2 as VALID_OPERATIONS,
|
|
1742
|
+
VALID_SEVERITIES2 as VALID_SEVERITIES,
|
|
1743
|
+
assembleStats,
|
|
1573
1744
|
betterAudit,
|
|
1574
1745
|
createAuditApi,
|
|
1575
1746
|
createAuditConsoleEndpoints,
|
|
1576
1747
|
createExportResponse,
|
|
1748
|
+
decodeCursor,
|
|
1749
|
+
defaultExtractor,
|
|
1750
|
+
encodeCursor,
|
|
1751
|
+
escapeLikePattern,
|
|
1577
1752
|
fromBearerToken,
|
|
1578
1753
|
fromCookie,
|
|
1579
1754
|
fromHeader,
|
|
1580
1755
|
getAuditContext,
|
|
1581
1756
|
handleMiddleware,
|
|
1757
|
+
interpretFilters,
|
|
1758
|
+
isAuditOperation,
|
|
1759
|
+
isAuditSeverity,
|
|
1582
1760
|
mergeAuditContext,
|
|
1583
1761
|
normalizeInput,
|
|
1584
1762
|
parseDuration,
|
|
1763
|
+
resolveTimeFilter,
|
|
1585
1764
|
runExport,
|
|
1586
|
-
runWithAuditContext
|
|
1765
|
+
runWithAuditContext,
|
|
1766
|
+
safeExtract,
|
|
1767
|
+
toCount
|
|
1587
1768
|
};
|
|
1588
1769
|
//# sourceMappingURL=index.js.map
|