@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.cjs +71 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -1
- package/dist/index.d.ts +34 -1
- package/dist/index.js +70 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
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,
|