@stotles/better-auth-audit-logs 0.4.0-rc.1

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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +319 -0
  3. package/dist/adapters/index.d.ts +1 -0
  4. package/dist/adapters/index.d.ts.map +1 -0
  5. package/dist/adapters/memory.d.ts +13 -0
  6. package/dist/adapters/memory.d.ts.map +1 -0
  7. package/dist/client.cjs +77 -0
  8. package/dist/client.d.ts +10 -0
  9. package/dist/client.d.ts.map +1 -0
  10. package/dist/client.js +13 -0
  11. package/dist/endpoints/get-log.d.ts +27 -0
  12. package/dist/endpoints/get-log.d.ts.map +1 -0
  13. package/dist/endpoints/index.d.ts +3 -0
  14. package/dist/endpoints/index.d.ts.map +1 -0
  15. package/dist/endpoints/insert-log.d.ts +44 -0
  16. package/dist/endpoints/insert-log.d.ts.map +1 -0
  17. package/dist/endpoints/list-logs.d.ts +40 -0
  18. package/dist/endpoints/list-logs.d.ts.map +1 -0
  19. package/dist/hooks/after.d.ts +6 -0
  20. package/dist/hooks/after.d.ts.map +1 -0
  21. package/dist/hooks/before.d.ts +6 -0
  22. package/dist/hooks/before.d.ts.map +1 -0
  23. package/dist/hooks/index.d.ts +2 -0
  24. package/dist/hooks/index.d.ts.map +1 -0
  25. package/dist/index.cjs +828 -0
  26. package/dist/index.d.ts +4 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +762 -0
  29. package/dist/internal.d.ts +16 -0
  30. package/dist/internal.d.ts.map +1 -0
  31. package/dist/plugin.d.ts +180 -0
  32. package/dist/plugin.d.ts.map +1 -0
  33. package/dist/schema.d.ts +109 -0
  34. package/dist/schema.d.ts.map +1 -0
  35. package/dist/types.d.ts +102 -0
  36. package/dist/types.d.ts.map +1 -0
  37. package/dist/utils/index.d.ts +7 -0
  38. package/dist/utils/index.d.ts.map +1 -0
  39. package/dist/utils/normalize-path.d.ts +1 -0
  40. package/dist/utils/normalize-path.d.ts.map +1 -0
  41. package/dist/utils/parse-metadata.d.ts +8 -0
  42. package/dist/utils/parse-metadata.d.ts.map +1 -0
  43. package/dist/utils/request-meta.d.ts +9 -0
  44. package/dist/utils/request-meta.d.ts.map +1 -0
  45. package/dist/utils/retry.d.ts +8 -0
  46. package/dist/utils/retry.d.ts.map +1 -0
  47. package/dist/utils/sanitize.d.ts +3 -0
  48. package/dist/utils/sanitize.d.ts.map +1 -0
  49. package/dist/utils/severity.d.ts +2 -0
  50. package/dist/utils/severity.d.ts.map +1 -0
  51. package/dist/utils/validate-entry.d.ts +8 -0
  52. package/dist/utils/validate-entry.d.ts.map +1 -0
  53. package/dist/utils/validate-metadata.d.ts +10 -0
  54. package/dist/utils/validate-metadata.d.ts.map +1 -0
  55. package/package.json +72 -0
@@ -0,0 +1,16 @@
1
+ import type { GenericEndpointContext } from "@better-auth/core";
2
+ import type { AuditLogEntry, AuditLogStatus, PathConfig, ResolvedOptions } from "./types";
3
+ interface BuildParams {
4
+ userId: string | null;
5
+ request: Request | undefined;
6
+ headers: Headers | undefined;
7
+ metadata?: Record<string, unknown>;
8
+ pathConfig?: PathConfig;
9
+ options: ResolvedOptions;
10
+ authOptions: GenericEndpointContext["context"]["options"];
11
+ logger?: GenericEndpointContext["context"]["logger"];
12
+ }
13
+ export declare function buildLogEntry(path: string, status: AuditLogStatus, params: BuildParams): Promise<Omit<AuditLogEntry, "id">>;
14
+ export declare function buildLogEntryFromAction(action: string, status: AuditLogStatus, params: Omit<BuildParams, "pathConfig">): Promise<Omit<AuditLogEntry, "id">>;
15
+ export declare function writeEntry(ctx: GenericEndpointContext, entry: Omit<AuditLogEntry, "id">, opts: ResolvedOptions, modelName: string): Promise<void>;
16
+ export {};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,eAAe,EAChB,MAAM,SAAS,CAAC;AAUjB,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,sBAAsB,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC;CAC3D;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CA+BpC;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAwBpC;AAED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,sBAAsB,EAC3B,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,EAChC,IAAI,EAAE,eAAe,EACrB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAuDf"}
@@ -0,0 +1,180 @@
1
+ import type { AuditLogOptions } from "./types";
2
+ export declare function auditLog(options?: AuditLogOptions): {
3
+ id: "audit-log";
4
+ schema: {
5
+ auditLog: {
6
+ modelName: string;
7
+ fields: {
8
+ userId: {
9
+ type: "string";
10
+ required: boolean;
11
+ references: {
12
+ model: string;
13
+ field: string;
14
+ onDelete: "set null";
15
+ };
16
+ index: boolean;
17
+ };
18
+ action: {
19
+ type: "string";
20
+ required: boolean;
21
+ sortable: boolean;
22
+ index: boolean;
23
+ };
24
+ status: {
25
+ type: "string";
26
+ required: boolean;
27
+ sortable: boolean;
28
+ };
29
+ severity: {
30
+ type: "string";
31
+ required: boolean;
32
+ sortable: boolean;
33
+ };
34
+ ipAddress: {
35
+ type: "string";
36
+ required: boolean;
37
+ };
38
+ userAgent: {
39
+ type: "string";
40
+ required: boolean;
41
+ returned: boolean;
42
+ };
43
+ metadata: {
44
+ type: "string";
45
+ required: boolean;
46
+ };
47
+ createdAt: {
48
+ type: "date";
49
+ required: boolean;
50
+ sortable: boolean;
51
+ index: boolean;
52
+ defaultValue: () => Date;
53
+ };
54
+ };
55
+ };
56
+ };
57
+ hooks: {
58
+ before: {
59
+ matcher: (context: import("better-auth").HookEndpointContext) => boolean;
60
+ handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
61
+ }[];
62
+ after: {
63
+ matcher: (context: import("better-auth").HookEndpointContext) => boolean;
64
+ handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
65
+ }[];
66
+ };
67
+ endpoints: {
68
+ listAuditLogs: import("better-call").StrictEndpoint<"/audit-log/list", {
69
+ method: "GET";
70
+ use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
71
+ session: {
72
+ session: Record<string, any> & {
73
+ id: string;
74
+ createdAt: Date;
75
+ updatedAt: Date;
76
+ userId: string;
77
+ expiresAt: Date;
78
+ token: string;
79
+ ipAddress?: string | null | undefined;
80
+ userAgent?: string | null | undefined;
81
+ };
82
+ user: Record<string, any> & {
83
+ id: string;
84
+ createdAt: Date;
85
+ updatedAt: Date;
86
+ email: string;
87
+ emailVerified: boolean;
88
+ name: string;
89
+ image?: string | null | undefined;
90
+ };
91
+ };
92
+ }>)[];
93
+ query: import("zod").ZodObject<{
94
+ userId: import("zod").ZodOptional<import("zod").ZodString>;
95
+ action: import("zod").ZodOptional<import("zod").ZodString>;
96
+ status: import("zod").ZodOptional<import("zod").ZodEnum<{
97
+ success: "success";
98
+ failed: "failed";
99
+ }>>;
100
+ from: import("zod").ZodOptional<import("zod").ZodString>;
101
+ to: import("zod").ZodOptional<import("zod").ZodString>;
102
+ limit: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodCoercedNumber<unknown>>>;
103
+ offset: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodCoercedNumber<unknown>>>;
104
+ }, import("zod/v4/core").$strip>;
105
+ }, import("./types").StorageReadResult>;
106
+ getAuditLog: import("better-call").StrictEndpoint<"/audit-log/:id", {
107
+ method: "GET";
108
+ use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
109
+ session: {
110
+ session: Record<string, any> & {
111
+ id: string;
112
+ createdAt: Date;
113
+ updatedAt: Date;
114
+ userId: string;
115
+ expiresAt: Date;
116
+ token: string;
117
+ ipAddress?: string | null | undefined;
118
+ userAgent?: string | null | undefined;
119
+ };
120
+ user: Record<string, any> & {
121
+ id: string;
122
+ createdAt: Date;
123
+ updatedAt: Date;
124
+ email: string;
125
+ emailVerified: boolean;
126
+ name: string;
127
+ image?: string | null | undefined;
128
+ };
129
+ };
130
+ }>)[];
131
+ }, import("./types").AuditLogEntry>;
132
+ insertAuditLog: import("better-call").StrictEndpoint<"/audit-log/insert", {
133
+ method: "POST";
134
+ use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
135
+ session: {
136
+ session: Record<string, any> & {
137
+ id: string;
138
+ createdAt: Date;
139
+ updatedAt: Date;
140
+ userId: string;
141
+ expiresAt: Date;
142
+ token: string;
143
+ ipAddress?: string | null | undefined;
144
+ userAgent?: string | null | undefined;
145
+ };
146
+ user: Record<string, any> & {
147
+ id: string;
148
+ createdAt: Date;
149
+ updatedAt: Date;
150
+ email: string;
151
+ emailVerified: boolean;
152
+ name: string;
153
+ image?: string | null | undefined;
154
+ };
155
+ };
156
+ }>)[];
157
+ body: import("zod").ZodObject<{
158
+ action: import("zod").ZodString;
159
+ status: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodEnum<{
160
+ success: "success";
161
+ failed: "failed";
162
+ }>>>;
163
+ severity: import("zod").ZodOptional<import("zod").ZodEnum<{
164
+ low: "low";
165
+ medium: "medium";
166
+ high: "high";
167
+ critical: "critical";
168
+ }>>;
169
+ metadata: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>>;
170
+ }, import("zod/v4/core").$strip>;
171
+ }, {
172
+ success: boolean;
173
+ }>;
174
+ };
175
+ rateLimit: {
176
+ pathMatcher: (path: string) => boolean;
177
+ window: number;
178
+ max: number;
179
+ }[];
180
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,eAAe,EAGhB,MAAM,SAAS,CAAC;AAqFjB,wBAAgB,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCAtB5B,CAAC;iCAEF,CAAC;;;;;;;;;6BAKsB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCAPvB,CAAC;iCAEF,CAAC;;;;;;;;;6BAKsB,CAAC;;;;;;;;;;;;;;;;iCAPvB,CAAC;iCAEF,CAAC;;;;;;;;;6BAKsB,CAAC;;;;;;;;;;;;;;;;;;;;;;;4BAyCjB,MAAM;;;;EAMjC"}
@@ -0,0 +1,109 @@
1
+ import type { AuditLogOptions } from "./types";
2
+ export declare const baseSchema: {
3
+ auditLog: {
4
+ modelName: string;
5
+ fields: {
6
+ userId: {
7
+ type: "string";
8
+ required: boolean;
9
+ references: {
10
+ model: string;
11
+ field: string;
12
+ onDelete: "set null";
13
+ };
14
+ index: boolean;
15
+ };
16
+ action: {
17
+ type: "string";
18
+ required: boolean;
19
+ sortable: boolean;
20
+ index: boolean;
21
+ };
22
+ status: {
23
+ type: "string";
24
+ required: boolean;
25
+ sortable: boolean;
26
+ };
27
+ severity: {
28
+ type: "string";
29
+ required: boolean;
30
+ sortable: boolean;
31
+ };
32
+ ipAddress: {
33
+ type: "string";
34
+ required: boolean;
35
+ };
36
+ userAgent: {
37
+ type: "string";
38
+ required: boolean;
39
+ returned: boolean;
40
+ };
41
+ metadata: {
42
+ type: "string";
43
+ required: boolean;
44
+ };
45
+ createdAt: {
46
+ type: "date";
47
+ required: boolean;
48
+ sortable: boolean;
49
+ index: boolean;
50
+ defaultValue: () => Date;
51
+ };
52
+ };
53
+ };
54
+ };
55
+ export declare function buildSchema(options?: AuditLogOptions): {
56
+ auditLog: {
57
+ modelName: string;
58
+ fields: {
59
+ userId: {
60
+ type: "string";
61
+ required: boolean;
62
+ references: {
63
+ model: string;
64
+ field: string;
65
+ onDelete: "set null";
66
+ };
67
+ index: boolean;
68
+ };
69
+ action: {
70
+ type: "string";
71
+ required: boolean;
72
+ sortable: boolean;
73
+ index: boolean;
74
+ };
75
+ status: {
76
+ type: "string";
77
+ required: boolean;
78
+ sortable: boolean;
79
+ };
80
+ severity: {
81
+ type: "string";
82
+ required: boolean;
83
+ sortable: boolean;
84
+ };
85
+ ipAddress: {
86
+ type: "string";
87
+ required: boolean;
88
+ };
89
+ userAgent: {
90
+ type: "string";
91
+ required: boolean;
92
+ returned: boolean;
93
+ };
94
+ metadata: {
95
+ type: "string";
96
+ required: boolean;
97
+ };
98
+ createdAt: {
99
+ type: "date";
100
+ required: boolean;
101
+ sortable: boolean;
102
+ index: boolean;
103
+ defaultValue: () => Date;
104
+ };
105
+ };
106
+ };
107
+ };
108
+ export declare function getModelName(options?: AuditLogOptions): string;
109
+ export declare function validateSchema(schema: ReturnType<typeof buildSchema>): void;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDtB,CAAC;AAEF,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEpD;AAED,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,MAAM,CAE9D;AAID,wBAAgB,cAAc,CAC5B,MAAM,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,GACrC,IAAI,CAkBN"}
@@ -0,0 +1,102 @@
1
+ import type { GenericEndpointContext } from "@better-auth/core";
2
+ export type AuditLogStatus = "success" | "failed";
3
+ export type AuditLogSeverity = "low" | "medium" | "high" | "critical";
4
+ export type PIIStrategy = "mask" | "hash" | "remove";
5
+ export interface AuditLogEntry {
6
+ id: string;
7
+ userId: string | null;
8
+ action: string;
9
+ status: AuditLogStatus;
10
+ severity: AuditLogSeverity;
11
+ ipAddress: string | null;
12
+ userAgent: string | null;
13
+ metadata: Record<string, unknown>;
14
+ createdAt: Date;
15
+ }
16
+ export interface StorageReadOptions {
17
+ userId?: string;
18
+ action?: string;
19
+ status?: AuditLogStatus;
20
+ from?: Date;
21
+ to?: Date;
22
+ limit: number;
23
+ offset: number;
24
+ }
25
+ export interface StorageReadResult {
26
+ entries: AuditLogEntry[];
27
+ total: number;
28
+ }
29
+ export interface AuditLogStorage {
30
+ write(entry: AuditLogEntry): Promise<void>;
31
+ read?(options: StorageReadOptions): Promise<StorageReadResult>;
32
+ readById?(id: string): Promise<AuditLogEntry | null>;
33
+ deleteOlderThan?(date: Date): Promise<number>;
34
+ }
35
+ export interface PIIRedactionOptions {
36
+ enabled: boolean;
37
+ fields?: string[];
38
+ strategy?: PIIStrategy;
39
+ }
40
+ export interface CaptureOptions {
41
+ ipAddress?: boolean;
42
+ userAgent?: boolean;
43
+ requestBody?: boolean;
44
+ }
45
+ export interface PathConfig {
46
+ severity?: AuditLogSeverity;
47
+ capture?: CaptureOptions;
48
+ }
49
+ export interface RetentionConfig {
50
+ enabled: boolean;
51
+ days: number;
52
+ }
53
+ export interface MetadataLimitsConfig {
54
+ maxBytes?: number;
55
+ maxDepth?: number;
56
+ }
57
+ export interface AuditLogOptions {
58
+ enabled?: boolean;
59
+ nonBlocking?: boolean;
60
+ storage?: AuditLogStorage;
61
+ paths?: (string | {
62
+ path: string;
63
+ config?: PathConfig;
64
+ })[];
65
+ beforePaths?: string[];
66
+ piiRedaction?: PIIRedactionOptions;
67
+ capture?: CaptureOptions;
68
+ retention?: RetentionConfig;
69
+ metadataLimits?: MetadataLimitsConfig | false;
70
+ schema?: {
71
+ auditLog?: {
72
+ modelName?: string;
73
+ fields?: Record<string, string>;
74
+ };
75
+ };
76
+ beforeLog?: (entry: Omit<AuditLogEntry, "id">, ctx: GenericEndpointContext) => Promise<Omit<AuditLogEntry, "id"> | null>;
77
+ afterLog?: (entry: AuditLogEntry) => Promise<void>;
78
+ onWriteError?: (error: unknown, entry: Omit<AuditLogEntry, "id">) => void;
79
+ }
80
+ export interface ResolvedMetadataLimits {
81
+ maxBytes: number;
82
+ maxDepth: number;
83
+ }
84
+ export interface ResolvedOptions {
85
+ enabled: boolean;
86
+ nonBlocking: boolean;
87
+ storage: AuditLogStorage | undefined;
88
+ capture: Required<CaptureOptions>;
89
+ piiRedaction: {
90
+ enabled: boolean;
91
+ fields?: string[];
92
+ strategy: PIIStrategy;
93
+ };
94
+ retention: RetentionConfig | undefined;
95
+ metadataLimits: ResolvedMetadataLimits | false;
96
+ beforePaths: readonly string[];
97
+ beforeLog: AuditLogOptions["beforeLog"];
98
+ afterLog: AuditLogOptions["afterLog"];
99
+ onWriteError: AuditLogOptions["onWriteError"];
100
+ shouldCapture: (path: string) => boolean;
101
+ getPathConfig: (path: string) => PathConfig | undefined;
102
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { normalizePath } from "./normalize-path";
2
+ export { inferSeverity } from "./severity";
3
+ export { extractRequestMeta } from "./request-meta";
4
+ export { redactPII, DEFAULT_PII_FIELDS } from "./sanitize";
5
+ export { parseMetadata } from "./parse-metadata";
6
+ export { validateEntry } from "./validate-entry";
7
+ export { withRetry } from "./retry";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function normalizePath(path: string): string;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-path.d.ts","sourceRoot":"","sources":["../../src/utils/normalize-path.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Safely parse metadata from a database record.
3
+ *
4
+ * The schema stores metadata as a JSON string, but the application type is
5
+ * Record<string, unknown>. This function centralizes the conversion and
6
+ * handles corrupt/malformed data gracefully.
7
+ */
8
+ export declare function parseMetadata(raw: unknown): Record<string, unknown>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-metadata.d.ts","sourceRoot":"","sources":["../../src/utils/parse-metadata.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoBnE"}
@@ -0,0 +1,9 @@
1
+ import type { BetterAuthOptions } from "better-auth";
2
+ type Logger = {
3
+ error: (message: string, ...args: unknown[]) => void;
4
+ };
5
+ export declare function extractRequestMeta(request: Request | undefined, headers: Headers | undefined, options: BetterAuthOptions, logger?: Logger): {
6
+ ipAddress: string | null;
7
+ userAgent: string | null;
8
+ };
9
+ export {};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-meta.d.ts","sourceRoot":"","sources":["../../src/utils/request-meta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAYrD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,OAAO,EAAE,iBAAiB,GACzB;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAKxD"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Retry an async operation with exponential backoff.
3
+ * Throws the last error if all retries are exhausted.
4
+ */
5
+ export declare function withRetry<T>(fn: () => Promise<T>, opts: {
6
+ maxRetries: number;
7
+ baseDelayMs: number;
8
+ }): Promise<T>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAChD,OAAO,CAAC,CAAC,CAAC,CAgBZ"}
@@ -0,0 +1,3 @@
1
+ import type { PIIRedactionOptions } from "../types";
2
+ export declare const DEFAULT_PII_FIELDS: string[];
3
+ export declare function redactPII(data: Record<string, unknown>, config: PIIRedactionOptions): Promise<Record<string, unknown>>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEpD,eAAO,MAAM,kBAAkB,UAY9B,CAAC;AAUF,wBAAsB,SAAS,CAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAoBlC"}
@@ -0,0 +1,2 @@
1
+ import type { AuditLogSeverity, AuditLogStatus } from "../types";
2
+ export declare function inferSeverity(action: string, status: AuditLogStatus): AuditLogSeverity;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severity.d.ts","sourceRoot":"","sources":["../../src/utils/severity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAiBjE,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,GACrB,gBAAgB,CAQlB"}
@@ -0,0 +1,8 @@
1
+ import type { AuditLogEntry } from "../types";
2
+ /**
3
+ * Validate that a beforeLog return value has all required fields.
4
+ * Returns the validated entry or null if validation fails.
5
+ */
6
+ export declare function validateEntry(entry: unknown, logger?: {
7
+ warn: (message: string, ...args: unknown[]) => void;
8
+ }): Omit<AuditLogEntry, "id"> | null;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-entry.d.ts","sourceRoot":"","sources":["../../src/utils/validate-entry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAiB9C;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,MAAM,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CAAE,GAC/D,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG,IAAI,CAUlC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Validate metadata size constraints to prevent abuse.
3
+ * Returns an error message if validation fails, null if valid.
4
+ */
5
+ export interface MetadataLimits {
6
+ maxBytes: number;
7
+ maxDepth: number;
8
+ }
9
+ export declare const DEFAULT_METADATA_LIMITS: MetadataLimits;
10
+ export declare function validateMetadataSize(metadata: Record<string, unknown>, limits?: MetadataLimits): string | null;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-metadata.d.ts","sourceRoot":"","sources":["../../src/utils/validate-metadata.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,uBAAuB,EAAE,cAGrC,CAAC;AAqBF,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,MAAM,GAAE,cAAwC,GAC/C,MAAM,GAAG,IAAI,CAYf"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@stotles/better-auth-audit-logs",
3
+ "version": "0.4.0-rc.1",
4
+ "description": "Audit log plugin for Better Auth. Captures auth lifecycle events, stores structured log entries, and exposes query endpoints with PII redaction and custom storage backends.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Ejiro Asiuwhu <ejiroasiuwhu10@gmail.com>",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/Stotles/better-auth-audit-logs.git"
11
+ },
12
+ "homepage": "https://github.com/Stotles/better-auth-audit-logs#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/Stotles/better-auth-audit-logs/issues"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "keywords": [
20
+ "better-auth",
21
+ "better-auth-plugin",
22
+ "audit-log",
23
+ "audit-trail",
24
+ "auth",
25
+ "authentication",
26
+ "security",
27
+ "logging",
28
+ "compliance",
29
+ "pii-redaction",
30
+ "session-tracking"
31
+ ],
32
+ "main": "./dist/index.cjs",
33
+ "types": "./dist/index.d.ts",
34
+ "exports": {
35
+ ".": {
36
+ "require": "./dist/index.cjs",
37
+ "import": "./dist/index.js",
38
+ "types": "./dist/index.d.ts"
39
+ },
40
+ "./client": {
41
+ "require": "./dist/client.cjs",
42
+ "import": "./dist/client.js",
43
+ "types": "./dist/client.d.ts"
44
+ }
45
+ },
46
+ "typesVersions": {
47
+ "*": {
48
+ "client": [
49
+ "./dist/client.d.ts"
50
+ ]
51
+ }
52
+ },
53
+ "files": [
54
+ "dist"
55
+ ],
56
+ "scripts": {
57
+ "build": "bun build src/index.ts src/client.ts --outdir dist --target node --external better-auth --external zod && bun build src/index.ts src/client.ts --outdir dist --target node --format cjs --entry-naming '[dir]/[name].cjs' --external better-auth --external zod && tsc -p tsconfig.build.json",
58
+ "test": "bun test",
59
+ "typecheck": "tsc --noEmit",
60
+ "check": "tsc --noEmit && bun test"
61
+ },
62
+ "peerDependencies": {
63
+ "better-auth": ">=1.0.0",
64
+ "zod": ">=3.0.0",
65
+ "typescript": "^5"
66
+ },
67
+ "devDependencies": {
68
+ "@types/bun": "latest",
69
+ "better-auth": "^1.5.5",
70
+ "zod": "^4.3.6"
71
+ }
72
+ }