@usebetterdev/audit-drizzle 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 CHANGED
@@ -21,19 +21,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  auditLogs: () => auditLogs,
24
- buildCursorCondition: () => buildCursorCondition,
25
24
  buildOrderBy: () => buildOrderBy,
26
25
  buildWhereConditions: () => buildWhereConditions,
27
- decodeCursor: () => decodeCursor,
26
+ decodeCursor: () => import_audit_core7.decodeCursor,
28
27
  drizzleAuditAdapter: () => drizzleAuditAdapter,
29
28
  drizzleSqliteAuditAdapter: () => drizzleSqliteAuditAdapter,
30
- encodeCursor: () => encodeCursor,
29
+ encodeCursor: () => import_audit_core7.encodeCursor,
31
30
  sqliteAuditLogs: () => sqliteAuditLogs,
32
31
  withAuditProxy: () => withAuditProxy
33
32
  });
34
33
  module.exports = __toCommonJS(index_exports);
35
34
 
36
35
  // src/adapter.ts
36
+ var import_audit_core3 = require("@usebetterdev/audit-core");
37
37
  var import_drizzle_orm2 = require("drizzle-orm");
38
38
 
39
39
  // src/schema.ts
@@ -77,23 +77,7 @@ var auditLogs = (0, import_pg_core.pgTable)(
77
77
  );
78
78
 
79
79
  // src/column-map.ts
80
- var VALID_OPERATIONS = /* @__PURE__ */ new Set([
81
- "INSERT",
82
- "UPDATE",
83
- "DELETE"
84
- ]);
85
- var VALID_SEVERITIES = /* @__PURE__ */ new Set([
86
- "low",
87
- "medium",
88
- "high",
89
- "critical"
90
- ]);
91
- function isAuditOperation(value) {
92
- return VALID_OPERATIONS.has(value);
93
- }
94
- function isAuditSeverity(value) {
95
- return VALID_SEVERITIES.has(value);
96
- }
80
+ var import_audit_core = require("@usebetterdev/audit-core");
97
81
  function auditLogToRow(log) {
98
82
  const row = {
99
83
  id: log.id,
@@ -141,7 +125,7 @@ function auditLogToRow(log) {
141
125
  return row;
142
126
  }
143
127
  function rowToAuditLog(row) {
144
- if (!isAuditOperation(row.operation)) {
128
+ if (!(0, import_audit_core.isAuditOperation)(row.operation)) {
145
129
  throw new Error(
146
130
  `Invalid audit operation: "${row.operation}". Expected one of: INSERT, UPDATE, DELETE`
147
131
  );
@@ -172,7 +156,7 @@ function rowToAuditLog(row) {
172
156
  log.description = row.description;
173
157
  }
174
158
  if (row.severity !== null && row.severity !== void 0) {
175
- if (!isAuditSeverity(row.severity)) {
159
+ if (!(0, import_audit_core.isAuditSeverity)(row.severity)) {
176
160
  throw new Error(
177
161
  `Invalid audit severity: "${row.severity}". Expected one of: low, medium, high, critical`
178
162
  );
@@ -198,87 +182,68 @@ function rowToAuditLog(row) {
198
182
  }
199
183
 
200
184
  // src/query.ts
201
- var import_audit_core = require("@usebetterdev/audit-core");
185
+ var import_audit_core2 = require("@usebetterdev/audit-core");
202
186
  var import_drizzle_orm = require("drizzle-orm");
203
- function escapeLikePattern(input) {
204
- return input.replace(/[%_\\]/g, "\\$&");
205
- }
206
- function resolveTimeFilter(filter) {
207
- if ("date" in filter && filter.date !== void 0) {
208
- return filter.date;
209
- }
210
- if ("duration" in filter && filter.duration !== void 0) {
211
- return (0, import_audit_core.parseDuration)(filter.duration);
212
- }
213
- throw new Error("TimeFilter must have either date or duration");
214
- }
215
- function buildWhereConditions(filters) {
216
- const conditions = [];
217
- if (filters.resource !== void 0) {
218
- conditions.push((0, import_drizzle_orm.eq)(auditLogs.tableName, filters.resource.tableName));
219
- if (filters.resource.recordId !== void 0) {
220
- conditions.push((0, import_drizzle_orm.eq)(auditLogs.recordId, filters.resource.recordId));
187
+ var FIELD_COLUMNS = {
188
+ tableName: auditLogs.tableName,
189
+ recordId: auditLogs.recordId,
190
+ actorId: auditLogs.actorId,
191
+ severity: auditLogs.severity,
192
+ operation: auditLogs.operation
193
+ };
194
+ function mapCondition(condition) {
195
+ switch (condition.kind) {
196
+ case "eq": {
197
+ return (0, import_drizzle_orm.eq)(FIELD_COLUMNS[condition.field], condition.value);
221
198
  }
222
- }
223
- if (filters.actorIds !== void 0 && filters.actorIds.length > 0) {
224
- if (filters.actorIds.length === 1) {
225
- conditions.push((0, import_drizzle_orm.eq)(auditLogs.actorId, filters.actorIds[0]));
226
- } else {
227
- conditions.push((0, import_drizzle_orm.inArray)(auditLogs.actorId, filters.actorIds));
199
+ case "in": {
200
+ return (0, import_drizzle_orm.inArray)(FIELD_COLUMNS[condition.field], condition.values);
228
201
  }
229
- }
230
- if (filters.severities !== void 0 && filters.severities.length > 0) {
231
- if (filters.severities.length === 1) {
232
- conditions.push((0, import_drizzle_orm.eq)(auditLogs.severity, filters.severities[0]));
233
- } else {
234
- conditions.push((0, import_drizzle_orm.inArray)(auditLogs.severity, filters.severities));
202
+ case "timestampGte": {
203
+ return (0, import_drizzle_orm.gte)(auditLogs.timestamp, condition.value);
235
204
  }
236
- }
237
- if (filters.operations !== void 0 && filters.operations.length > 0) {
238
- if (filters.operations.length === 1) {
239
- conditions.push((0, import_drizzle_orm.eq)(auditLogs.operation, filters.operations[0]));
240
- } else {
241
- conditions.push((0, import_drizzle_orm.inArray)(auditLogs.operation, filters.operations));
205
+ case "timestampLte": {
206
+ return (0, import_drizzle_orm.lte)(auditLogs.timestamp, condition.value);
242
207
  }
243
- }
244
- if (filters.since !== void 0) {
245
- conditions.push((0, import_drizzle_orm.gte)(auditLogs.timestamp, resolveTimeFilter(filters.since)));
246
- }
247
- if (filters.until !== void 0) {
248
- conditions.push((0, import_drizzle_orm.lte)(auditLogs.timestamp, resolveTimeFilter(filters.until)));
249
- }
250
- if (filters.searchText !== void 0 && filters.searchText.length > 0) {
251
- const escaped = escapeLikePattern(filters.searchText);
252
- const pattern = `%${escaped}%`;
253
- const searchCondition = (0, import_drizzle_orm.or)(
254
- (0, import_drizzle_orm.ilike)(auditLogs.label, pattern),
255
- (0, import_drizzle_orm.ilike)(auditLogs.description, pattern)
256
- );
257
- if (searchCondition !== void 0) {
258
- conditions.push(searchCondition);
208
+ case "search": {
209
+ return (0, import_drizzle_orm.or)(
210
+ (0, import_drizzle_orm.ilike)(auditLogs.label, condition.pattern),
211
+ (0, import_drizzle_orm.ilike)(auditLogs.description, condition.pattern)
212
+ );
213
+ }
214
+ case "compliance": {
215
+ return import_drizzle_orm.sql`${auditLogs.compliance} @> ${JSON.stringify(condition.tags)}::jsonb`;
216
+ }
217
+ case "cursor": {
218
+ const tsCompare = condition.sortOrder === "asc" ? import_drizzle_orm.gt : import_drizzle_orm.lt;
219
+ const idCompare = condition.sortOrder === "asc" ? import_drizzle_orm.gt : import_drizzle_orm.lt;
220
+ return (0, import_drizzle_orm.or)(
221
+ tsCompare(auditLogs.timestamp, condition.timestamp),
222
+ (0, import_drizzle_orm.and)(
223
+ (0, import_drizzle_orm.eq)(auditLogs.timestamp, condition.timestamp),
224
+ idCompare(auditLogs.id, condition.id)
225
+ )
226
+ );
259
227
  }
260
228
  }
261
- if (filters.compliance !== void 0 && filters.compliance.length > 0) {
262
- conditions.push(
263
- import_drizzle_orm.sql`${auditLogs.compliance} @> ${JSON.stringify(filters.compliance)}::jsonb`
264
- );
229
+ }
230
+ function buildWhereConditions(filters, cursor, sortOrder) {
231
+ const decoded = cursor !== void 0 ? (0, import_audit_core2.decodeCursor)(cursor) : void 0;
232
+ const irConditions = (0, import_audit_core2.interpretFilters)(filters, {
233
+ cursor: decoded,
234
+ sortOrder
235
+ });
236
+ const sqlConditions = [];
237
+ for (const c of irConditions) {
238
+ const mapped = mapCondition(c);
239
+ if (mapped !== void 0) {
240
+ sqlConditions.push(mapped);
241
+ }
265
242
  }
266
- if (conditions.length === 0) {
243
+ if (sqlConditions.length === 0) {
267
244
  return void 0;
268
245
  }
269
- return (0, import_drizzle_orm.and)(...conditions);
270
- }
271
- function buildCursorCondition(cursor, sortOrder) {
272
- const decoded = decodeCursor(cursor);
273
- const tsCompare = sortOrder === "asc" ? import_drizzle_orm.gt : import_drizzle_orm.lt;
274
- const idCompare = sortOrder === "asc" ? import_drizzle_orm.gt : import_drizzle_orm.lt;
275
- return (0, import_drizzle_orm.or)(
276
- tsCompare(auditLogs.timestamp, decoded.timestamp),
277
- (0, import_drizzle_orm.and)(
278
- (0, import_drizzle_orm.eq)(auditLogs.timestamp, decoded.timestamp),
279
- idCompare(auditLogs.id, decoded.id)
280
- )
281
- );
246
+ return (0, import_drizzle_orm.and)(...sqlConditions);
282
247
  }
283
248
  function buildOrderBy(sortOrder) {
284
249
  if (sortOrder === "asc") {
@@ -286,47 +251,10 @@ function buildOrderBy(sortOrder) {
286
251
  }
287
252
  return [(0, import_drizzle_orm.desc)(auditLogs.timestamp), (0, import_drizzle_orm.desc)(auditLogs.id)];
288
253
  }
289
- function encodeCursor(timestamp2, id) {
290
- const payload = JSON.stringify({ t: timestamp2.toISOString(), i: id });
291
- return btoa(payload);
292
- }
293
- var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
294
- function decodeCursor(cursor) {
295
- let parsed;
296
- try {
297
- parsed = JSON.parse(atob(cursor));
298
- } catch {
299
- throw new Error("Invalid cursor: failed to decode");
300
- }
301
- if (typeof parsed !== "object" || parsed === null || !("t" in parsed) || !("i" in parsed)) {
302
- throw new Error("Invalid cursor: missing required fields");
303
- }
304
- const { t, i } = parsed;
305
- if (typeof t !== "string" || typeof i !== "string") {
306
- throw new Error("Invalid cursor: fields must be strings");
307
- }
308
- const timestamp2 = new Date(t);
309
- if (isNaN(timestamp2.getTime())) {
310
- throw new Error("Invalid cursor: invalid timestamp");
311
- }
312
- if (!UUID_PATTERN.test(i)) {
313
- throw new Error("Invalid cursor: id must be a valid UUID");
314
- }
315
- return { timestamp: timestamp2, id: i };
316
- }
317
254
 
318
255
  // src/adapter.ts
319
256
  var DEFAULT_LIMIT = 50;
320
257
  var MAX_LIMIT = 250;
321
- function toCount(value) {
322
- if (typeof value === "number") {
323
- return value;
324
- }
325
- if (typeof value === "string") {
326
- return Number(value);
327
- }
328
- return 0;
329
- }
330
258
  function drizzleAuditAdapter(db) {
331
259
  return {
332
260
  async writeLog(log) {
@@ -336,9 +264,7 @@ function drizzleAuditAdapter(db) {
336
264
  async queryLogs(spec) {
337
265
  const sortOrder = spec.sortOrder ?? "desc";
338
266
  const limit = Math.min(spec.limit ?? DEFAULT_LIMIT, MAX_LIMIT);
339
- const whereCondition = buildWhereConditions(spec.filters);
340
- const cursorCondition = spec.cursor !== void 0 ? buildCursorCondition(spec.cursor, sortOrder) : void 0;
341
- const combined = (0, import_drizzle_orm2.and)(whereCondition, cursorCondition);
267
+ const combined = buildWhereConditions(spec.filters, spec.cursor, sortOrder);
342
268
  const fetchLimit = limit + 1;
343
269
  const orderColumns = buildOrderBy(sortOrder);
344
270
  const query = db.select().from(auditLogs).where(combined).orderBy(...orderColumns).limit(fetchLimit);
@@ -348,7 +274,7 @@ function drizzleAuditAdapter(db) {
348
274
  const entries = resultRows.map(rowToAuditLog);
349
275
  const lastRow = resultRows[resultRows.length - 1];
350
276
  if (hasNextPage && lastRow !== void 0) {
351
- return { entries, nextCursor: encodeCursor(lastRow.timestamp, lastRow.id) };
277
+ return { entries, nextCursor: (0, import_audit_core3.encodeCursor)(lastRow.timestamp, lastRow.id) };
352
278
  }
353
279
  return { entries };
354
280
  },
@@ -422,7 +348,7 @@ function drizzleAuditAdapter(db) {
422
348
  operationRows,
423
349
  severityRows
424
350
  ] = results;
425
- return assembleStats(
351
+ return (0, import_audit_core3.assembleStats)(
426
352
  summaryRows,
427
353
  eventsPerDayRows,
428
354
  topActorsRows,
@@ -433,42 +359,9 @@ function drizzleAuditAdapter(db) {
433
359
  }
434
360
  };
435
361
  }
436
- function assembleStats(summaryRows, eventsPerDayRows, topActorsRows, topTablesRows, operationRows, severityRows) {
437
- const summary = summaryRows[0];
438
- const totalLogs = summary !== void 0 ? toCount(summary.totalLogs) : 0;
439
- const tablesAudited = summary !== void 0 ? toCount(summary.tablesAudited) : 0;
440
- const eventsPerDay = eventsPerDayRows.map((row) => ({
441
- date: row.date instanceof Date ? row.date.toISOString().split("T")[0] : String(row.date),
442
- count: toCount(row.count)
443
- }));
444
- const topActors = topActorsRows.map((row) => ({
445
- actorId: String(row.actorId),
446
- count: toCount(row.count)
447
- }));
448
- const topTables = topTablesRows.map((row) => ({
449
- tableName: String(row.tableName),
450
- count: toCount(row.count)
451
- }));
452
- const operationBreakdown = {};
453
- for (const row of operationRows) {
454
- operationBreakdown[String(row.operation)] = toCount(row.count);
455
- }
456
- const severityBreakdown = {};
457
- for (const row of severityRows) {
458
- severityBreakdown[String(row.severity)] = toCount(row.count);
459
- }
460
- return {
461
- totalLogs,
462
- tablesAudited,
463
- eventsPerDay,
464
- topActors,
465
- topTables,
466
- operationBreakdown,
467
- severityBreakdown
468
- };
469
- }
470
362
 
471
363
  // src/sqlite-adapter.ts
364
+ var import_audit_core6 = require("@usebetterdev/audit-core");
472
365
  var import_drizzle_orm4 = require("drizzle-orm");
473
366
 
474
367
  // src/sqlite-schema.ts
@@ -512,23 +405,7 @@ var sqliteAuditLogs = (0, import_sqlite_core.sqliteTable)(
512
405
  );
513
406
 
514
407
  // 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
- }
408
+ var import_audit_core4 = require("@usebetterdev/audit-core");
532
409
  function sqliteAuditLogToRow(log) {
533
410
  const row = {
534
411
  id: log.id,
@@ -576,7 +453,7 @@ function sqliteAuditLogToRow(log) {
576
453
  return row;
577
454
  }
578
455
  function sqliteRowToAuditLog(row) {
579
- if (!isAuditOperation2(row.operation)) {
456
+ if (!(0, import_audit_core4.isAuditOperation)(row.operation)) {
580
457
  throw new Error(
581
458
  `Invalid audit operation: "${row.operation}". Expected one of: INSERT, UPDATE, DELETE`
582
459
  );
@@ -607,7 +484,7 @@ function sqliteRowToAuditLog(row) {
607
484
  log.description = row.description;
608
485
  }
609
486
  if (row.severity !== null && row.severity !== void 0) {
610
- if (!isAuditSeverity2(row.severity)) {
487
+ if (!(0, import_audit_core4.isAuditSeverity)(row.severity)) {
611
488
  throw new Error(
612
489
  `Invalid audit severity: "${row.severity}". Expected one of: low, medium, high, critical`
613
490
  );
@@ -633,89 +510,74 @@ function sqliteRowToAuditLog(row) {
633
510
  }
634
511
 
635
512
  // src/sqlite-query.ts
636
- var import_audit_core2 = require("@usebetterdev/audit-core");
513
+ var import_audit_core5 = require("@usebetterdev/audit-core");
637
514
  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));
515
+ var FIELD_COLUMNS2 = {
516
+ tableName: sqliteAuditLogs.tableName,
517
+ recordId: sqliteAuditLogs.recordId,
518
+ actorId: sqliteAuditLogs.actorId,
519
+ severity: sqliteAuditLogs.severity,
520
+ operation: sqliteAuditLogs.operation
521
+ };
522
+ function mapCondition2(condition) {
523
+ switch (condition.kind) {
524
+ case "eq": {
525
+ return (0, import_drizzle_orm3.eq)(FIELD_COLUMNS2[condition.field], condition.value);
656
526
  }
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));
527
+ case "in": {
528
+ return (0, import_drizzle_orm3.inArray)(FIELD_COLUMNS2[condition.field], condition.values);
663
529
  }
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));
530
+ case "timestampGte": {
531
+ return (0, import_drizzle_orm3.gte)(sqliteAuditLogs.timestamp, condition.value);
670
532
  }
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));
533
+ case "timestampLte": {
534
+ return (0, import_drizzle_orm3.lte)(sqliteAuditLogs.timestamp, condition.value);
677
535
  }
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);
536
+ case "search": {
537
+ return (0, import_drizzle_orm3.or)(
538
+ (0, import_drizzle_orm3.like)(sqliteAuditLogs.label, condition.pattern),
539
+ (0, import_drizzle_orm3.like)(sqliteAuditLogs.description, condition.pattern)
540
+ );
694
541
  }
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})`
542
+ case "compliance": {
543
+ const tagConditions = [];
544
+ for (const tag of condition.tags) {
545
+ tagConditions.push(
546
+ import_drizzle_orm3.sql`EXISTS (SELECT 1 FROM json_each(${sqliteAuditLogs.compliance}) WHERE value = ${tag})`
547
+ );
548
+ }
549
+ return (0, import_drizzle_orm3.and)(...tagConditions);
550
+ }
551
+ case "cursor": {
552
+ const tsCompare = condition.sortOrder === "asc" ? import_drizzle_orm3.gt : import_drizzle_orm3.lt;
553
+ const idCompare = condition.sortOrder === "asc" ? import_drizzle_orm3.gt : import_drizzle_orm3.lt;
554
+ return (0, import_drizzle_orm3.or)(
555
+ tsCompare(sqliteAuditLogs.timestamp, condition.timestamp),
556
+ (0, import_drizzle_orm3.and)(
557
+ (0, import_drizzle_orm3.eq)(sqliteAuditLogs.timestamp, condition.timestamp),
558
+ idCompare(sqliteAuditLogs.id, condition.id)
559
+ )
700
560
  );
701
561
  }
702
562
  }
703
- if (conditions.length === 0) {
563
+ }
564
+ function buildSqliteWhereConditions(filters, cursor, sortOrder) {
565
+ const decoded = cursor !== void 0 ? (0, import_audit_core5.decodeCursor)(cursor) : void 0;
566
+ const irConditions = (0, import_audit_core5.interpretFilters)(filters, {
567
+ cursor: decoded,
568
+ sortOrder
569
+ });
570
+ const sqlConditions = [];
571
+ for (const c of irConditions) {
572
+ const mapped = mapCondition2(c);
573
+ if (mapped !== void 0) {
574
+ sqlConditions.push(mapped);
575
+ }
576
+ }
577
+ if (sqlConditions.length === 0) {
704
578
  return void 0;
705
579
  }
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
- );
580
+ return (0, import_drizzle_orm3.and)(...sqlConditions);
719
581
  }
720
582
  function buildSqliteOrderBy(sortOrder) {
721
583
  if (sortOrder === "asc") {
@@ -723,47 +585,10 @@ function buildSqliteOrderBy(sortOrder) {
723
585
  }
724
586
  return [(0, import_drizzle_orm3.desc)(sqliteAuditLogs.timestamp), (0, import_drizzle_orm3.desc)(sqliteAuditLogs.id)];
725
587
  }
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
588
 
755
589
  // src/sqlite-adapter.ts
756
590
  var DEFAULT_LIMIT2 = 50;
757
591
  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
592
  function drizzleSqliteAuditAdapter(db) {
768
593
  return {
769
594
  async writeLog(log) {
@@ -773,9 +598,7 @@ function drizzleSqliteAuditAdapter(db) {
773
598
  async queryLogs(spec) {
774
599
  const sortOrder = spec.sortOrder ?? "desc";
775
600
  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);
601
+ const combined = buildSqliteWhereConditions(spec.filters, spec.cursor, sortOrder);
779
602
  const fetchLimit = limit + 1;
780
603
  const orderColumns = buildSqliteOrderBy(sortOrder);
781
604
  const query = db.select().from(sqliteAuditLogs).where(combined).orderBy(...orderColumns).limit(fetchLimit);
@@ -785,7 +608,7 @@ function drizzleSqliteAuditAdapter(db) {
785
608
  const entries = resultRows.map(sqliteRowToAuditLog);
786
609
  const lastRow = resultRows[resultRows.length - 1];
787
610
  if (hasNextPage && lastRow !== void 0) {
788
- return { entries, nextCursor: encodeSqliteCursor(lastRow.timestamp, lastRow.id) };
611
+ return { entries, nextCursor: (0, import_audit_core6.encodeCursor)(lastRow.timestamp, lastRow.id) };
789
612
  }
790
613
  return { entries };
791
614
  },
@@ -808,7 +631,7 @@ function drizzleSqliteAuditAdapter(db) {
808
631
  }
809
632
  await db.delete(sqliteAuditLogs).where((0, import_drizzle_orm4.and)(...conditions));
810
633
  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;
634
+ const deletedCount = changesResult[0] !== void 0 ? (0, import_audit_core6.toCount)(changesResult[0].count) : 0;
812
635
  return { deletedCount };
813
636
  },
814
637
  async getStats(options) {
@@ -853,7 +676,7 @@ function drizzleSqliteAuditAdapter(db) {
853
676
  operationRows,
854
677
  severityRows
855
678
  ] = results;
856
- return assembleStats2(
679
+ return (0, import_audit_core6.assembleStats)(
857
680
  summaryRows,
858
681
  eventsPerDayRows,
859
682
  topActorsRows,
@@ -864,40 +687,6 @@ function drizzleSqliteAuditAdapter(db) {
864
687
  }
865
688
  };
866
689
  }
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
690
 
902
691
  // src/proxy.ts
903
692
  var import_drizzle_orm5 = require("drizzle-orm");
@@ -1390,10 +1179,12 @@ async function fireCaptureLog(result, ctx, state) {
1390
1179
  }
1391
1180
  }
1392
1181
  }
1182
+
1183
+ // src/index.ts
1184
+ var import_audit_core7 = require("@usebetterdev/audit-core");
1393
1185
  // Annotate the CommonJS export names for ESM import in node:
1394
1186
  0 && (module.exports = {
1395
1187
  auditLogs,
1396
- buildCursorCondition,
1397
1188
  buildOrderBy,
1398
1189
  buildWhereConditions,
1399
1190
  decodeCursor,