@usebetterdev/audit-core 0.5.0-beta.1 → 0.5.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.d.ts CHANGED
@@ -104,6 +104,31 @@ declare class AuditQueryBuilder {
104
104
  list(): Promise<AuditQueryResult>;
105
105
  }
106
106
 
107
+ /** Options for `createExportResponse()`. */
108
+ interface ExportResponseOptions {
109
+ /** Output format. Default: `"csv"`. */
110
+ format?: "csv" | "json";
111
+ /** JSON output style. Default: `"ndjson"`. */
112
+ jsonStyle?: "ndjson" | "array";
113
+ /** Rows per database round-trip. */
114
+ batchSize?: number;
115
+ /** CSV delimiter character. */
116
+ csvDelimiter?: string;
117
+ /** Optional query builder to filter exported entries. */
118
+ query?: AuditQueryBuilder;
119
+ /** Custom filename stem (without extension). Default: `"audit-export-YYYY-MM-DD"`. */
120
+ filename?: string;
121
+ }
122
+ /**
123
+ * Create a streaming `Response` from the audit export engine.
124
+ *
125
+ * Uses `TransformStream` + `TextEncoderStream` to bridge the string-based
126
+ * `runExport()` output to a binary `ReadableStream` suitable for `new Response()`.
127
+ * The export runs asynchronously — the Response is returned immediately so the
128
+ * first byte can arrive before all rows are read.
129
+ */
130
+ declare function createExportResponse(executor: QueryExecutor, options?: ExportResponseOptions): Response;
131
+
107
132
  type AuditOperation = "INSERT" | "UPDATE" | "DELETE";
108
133
  /** Retention policy controlling automatic and CLI-driven purge of old audit logs. */
109
134
  interface RetentionPolicy {
@@ -333,6 +358,14 @@ interface BetterAuditInstance {
333
358
  * regardless of export size. Requires `queryLogs` on the database adapter.
334
359
  */
335
360
  export(options: ExportOptions): Promise<ExportResult>;
361
+ /**
362
+ * Create a streaming HTTP `Response` for downloading audit logs.
363
+ *
364
+ * Returns a standard `Response` with correct Content-Type, Content-Disposition,
365
+ * and Cache-Control headers. The body is a streaming `ReadableStream` backed
366
+ * by the export engine. Requires `queryLogs` on the database adapter.
367
+ */
368
+ exportResponse(options?: ExportResponseOptions): Response;
336
369
  withContext<T>(context: AuditContext, fn: () => Promise<T>): Promise<T>;
337
370
  /**
338
371
  * Register an enrichment config for a table/operation pair.
@@ -568,4 +601,4 @@ declare function fromHeader(headerName: string): ValueExtractor;
568
601
  */
569
602
  declare function handleMiddleware(extractor: ContextExtractor, request: Request, next: () => Promise<void>, options?: MiddlewareHandlerOptions): Promise<void>;
570
603
 
571
- 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 ExportResult, type MiddlewareHandlerOptions, type QueryExecutor, type ResourceFilter, type RetentionPolicy, type TimeFilter, type ValueExtractor, betterAudit, createAuditApi, createAuditConsoleEndpoints, fromBearerToken, fromCookie, fromHeader, getAuditContext, handleMiddleware, mergeAuditContext, normalizeInput, parseDuration, runExport, runWithAuditContext };
604
+ 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 RetentionPolicy, type TimeFilter, type ValueExtractor, betterAudit, createAuditApi, createAuditConsoleEndpoints, createExportResponse, fromBearerToken, fromCookie, fromHeader, getAuditContext, handleMiddleware, mergeAuditContext, normalizeInput, parseDuration, runExport, runWithAuditContext };
package/dist/index.js CHANGED
@@ -1119,6 +1119,65 @@ function createAuditConsoleEndpoints(api) {
1119
1119
  ];
1120
1120
  }
1121
1121
 
1122
+ // src/export-response.ts
1123
+ function contentTypeForFormat(format, jsonStyle) {
1124
+ if (format === "csv") {
1125
+ return "text/csv; charset=utf-8";
1126
+ }
1127
+ if (jsonStyle === "ndjson") {
1128
+ return "application/x-ndjson; charset=utf-8";
1129
+ }
1130
+ return "application/json; charset=utf-8";
1131
+ }
1132
+ function fileExtensionForFormat(format, jsonStyle) {
1133
+ if (format === "csv") {
1134
+ return ".csv";
1135
+ }
1136
+ if (jsonStyle === "ndjson") {
1137
+ return ".ndjson";
1138
+ }
1139
+ return ".json";
1140
+ }
1141
+ function formatDate(date) {
1142
+ const year = date.getFullYear();
1143
+ const month = String(date.getMonth() + 1).padStart(2, "0");
1144
+ const day = String(date.getDate()).padStart(2, "0");
1145
+ return `${year}-${month}-${day}`;
1146
+ }
1147
+ function sanitiseFilename(name) {
1148
+ return name.replace(/["\\\r\n\x00-\x1f]/g, "");
1149
+ }
1150
+ function createExportResponse(executor, options = {}) {
1151
+ const format = options.format ?? "csv";
1152
+ const jsonStyle = options.jsonStyle ?? "ndjson";
1153
+ const stem = options.filename ?? `audit-export-${formatDate(/* @__PURE__ */ new Date())}`;
1154
+ const extension = fileExtensionForFormat(format, jsonStyle);
1155
+ const fullFilename = sanitiseFilename(`${stem}${extension}`);
1156
+ const contentType = contentTypeForFormat(format, jsonStyle);
1157
+ const transform = new TransformStream();
1158
+ const encoder = new TextEncoderStream();
1159
+ const readable = transform.readable.pipeThrough(encoder);
1160
+ runExport(executor, {
1161
+ format,
1162
+ jsonStyle,
1163
+ output: transform.writable,
1164
+ ...options.batchSize !== void 0 && { batchSize: options.batchSize },
1165
+ ...options.csvDelimiter !== void 0 && {
1166
+ csvDelimiter: options.csvDelimiter
1167
+ },
1168
+ ...options.query !== void 0 && { query: options.query }
1169
+ }).catch(() => {
1170
+ });
1171
+ return new Response(readable, {
1172
+ status: 200,
1173
+ headers: {
1174
+ "Content-Type": contentType,
1175
+ "Content-Disposition": `attachment; filename="${fullFilename}"`,
1176
+ "Cache-Control": "no-cache"
1177
+ }
1178
+ });
1179
+ }
1180
+
1122
1181
  // src/retention.ts
1123
1182
  function validateRetentionPolicy(policy) {
1124
1183
  if (!Number.isInteger(policy.days) || !Number.isFinite(policy.days) || policy.days <= 0) {
@@ -1283,6 +1342,15 @@ function betterAudit(config) {
1283
1342
  const queryLogs = database.queryLogs;
1284
1343
  return runExport((spec) => queryLogs(spec), options);
1285
1344
  }
1345
+ function exportResponse(options) {
1346
+ if (database.queryLogs === void 0) {
1347
+ throw new Error(
1348
+ "audit.exportResponse() requires a database adapter that implements queryLogs(). Check that your ORM adapter supports querying."
1349
+ );
1350
+ }
1351
+ const queryLogs = database.queryLogs;
1352
+ return createExportResponse((spec) => queryLogs(spec), options);
1353
+ }
1286
1354
  if (config.console) {
1287
1355
  const api = createAuditApi(database, registry, config.maxQueryLimit);
1288
1356
  const endpoints = createAuditConsoleEndpoints(api);
@@ -1292,7 +1360,7 @@ function betterAudit(config) {
1292
1360
  endpoints
1293
1361
  });
1294
1362
  }
1295
- return { captureLog, query, export: exportLogs, withContext, enrich, onBeforeLog, onAfterLog, retentionPolicy };
1363
+ return { captureLog, query, export: exportLogs, exportResponse, withContext, enrich, onBeforeLog, onAfterLog, retentionPolicy };
1296
1364
  }
1297
1365
 
1298
1366
  // src/audit-log-schema.ts
@@ -1500,6 +1568,7 @@ export {
1500
1568
  betterAudit,
1501
1569
  createAuditApi,
1502
1570
  createAuditConsoleEndpoints,
1571
+ createExportResponse,
1503
1572
  fromBearerToken,
1504
1573
  fromCookie,
1505
1574
  fromHeader,