@richardmcquiston01/error-log-adapter 0.1.0 → 0.3.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 +883 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +472 -1
- package/dist/index.d.ts +472 -1
- package/dist/index.mjs +870 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -2
package/dist/index.d.cts
CHANGED
|
@@ -88,4 +88,475 @@ declare class CompositeErrorAdapter<TCode extends string = string> implements Er
|
|
|
88
88
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
/** Event handler slot. Typed loosely so real DOM `IDBTransaction` objects fit. */
|
|
92
|
+
type IdbHandler = ((event: never) => unknown) | null;
|
|
93
|
+
/** The subset of an `IDBObjectStore` this adapter uses. */
|
|
94
|
+
interface IdbObjectStoreLike {
|
|
95
|
+
add(value: unknown): unknown;
|
|
96
|
+
}
|
|
97
|
+
/** The subset of an `IDBTransaction` this adapter uses. */
|
|
98
|
+
interface IdbTransactionLike {
|
|
99
|
+
objectStore(name: string): IdbObjectStoreLike;
|
|
100
|
+
oncomplete: IdbHandler;
|
|
101
|
+
onerror: IdbHandler;
|
|
102
|
+
onabort: IdbHandler;
|
|
103
|
+
readonly error?: {
|
|
104
|
+
message?: string;
|
|
105
|
+
} | null;
|
|
106
|
+
}
|
|
107
|
+
/** The subset of an `IDBDatabase` this adapter uses. */
|
|
108
|
+
interface IdbDatabaseLike {
|
|
109
|
+
transaction(storeNames: string, mode: 'readwrite'): IdbTransactionLike;
|
|
110
|
+
}
|
|
111
|
+
/** The subset of an `IDBDatabase` available inside `onupgradeneeded`. */
|
|
112
|
+
interface IdbUpgradeDatabaseLike {
|
|
113
|
+
readonly objectStoreNames: {
|
|
114
|
+
contains(name: string): boolean;
|
|
115
|
+
};
|
|
116
|
+
createObjectStore(name: string, options: {
|
|
117
|
+
keyPath: string;
|
|
118
|
+
}): {
|
|
119
|
+
createIndex(name: string, keyPath: string): unknown;
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/** A stored record: the serialized entry plus its generated UUID key. */
|
|
123
|
+
interface IndexedDbErrorRecord extends SerializedErrorLogEntry {
|
|
124
|
+
id: string;
|
|
125
|
+
}
|
|
126
|
+
interface IndexedDbErrorOptions {
|
|
127
|
+
/** Object store to write to. Defaults to `error_log`. */
|
|
128
|
+
storeName?: string;
|
|
129
|
+
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
130
|
+
prefix?: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Creates the error log object store (UUID `id` key, `timestamp` index).
|
|
134
|
+
* Call it from your `onupgradeneeded` handler. Does nothing if it already exists.
|
|
135
|
+
*/
|
|
136
|
+
declare function createErrorLogStore(database: IdbUpgradeDatabaseLike, storeName?: string): void;
|
|
137
|
+
declare class IndexedDbErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
138
|
+
private readonly database;
|
|
139
|
+
private readonly storeName;
|
|
140
|
+
private readonly prefix;
|
|
141
|
+
constructor(database: IdbDatabaseLike, options?: IndexedDbErrorOptions);
|
|
142
|
+
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
143
|
+
/** Resolves once the transaction commits; rejects if it errors or aborts. */
|
|
144
|
+
private write;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The only thing this adapter needs from a SQLite driver: run one statement
|
|
149
|
+
* with positional (`?`) parameters. `bun:sqlite` already matches this shape.
|
|
150
|
+
* Other drivers need a one-line wrapper, for example:
|
|
151
|
+
*
|
|
152
|
+
* ```ts
|
|
153
|
+
* // better-sqlite3 or node:sqlite
|
|
154
|
+
* const client: SqliteClientLike = {
|
|
155
|
+
* run: (sql, params) => db.prepare(sql).run(...params),
|
|
156
|
+
* };
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
interface SqliteClientLike {
|
|
160
|
+
run(sql: string, params: unknown[]): unknown;
|
|
161
|
+
}
|
|
162
|
+
interface SqliteErrorOptions {
|
|
163
|
+
/** Table to write to. Defaults to `error_log`. Letters, digits and `_` only. */
|
|
164
|
+
tableName?: string;
|
|
165
|
+
/** Create the table (and index) on first use. Defaults to `true`. */
|
|
166
|
+
createTable?: boolean;
|
|
167
|
+
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
168
|
+
prefix?: string;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Returns the statements that create the error log table and its index.
|
|
172
|
+
* Use this to run your own migration when `createTable` is disabled.
|
|
173
|
+
*/
|
|
174
|
+
declare function buildCreateErrorLogTableSql(tableName?: string): string[];
|
|
175
|
+
declare class SqliteErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
176
|
+
private readonly client;
|
|
177
|
+
private readonly tableName;
|
|
178
|
+
private readonly createTable;
|
|
179
|
+
private readonly prefix;
|
|
180
|
+
private tableReady;
|
|
181
|
+
/** @throws {RangeError} if `options.tableName` is not a plain identifier. */
|
|
182
|
+
constructor(client: SqliteClientLike, options?: SqliteErrorOptions);
|
|
183
|
+
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
184
|
+
/** Creates the table once. A failed attempt is retried on the next log call. */
|
|
185
|
+
private ensureTable;
|
|
186
|
+
private runCreateStatements;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The subset of the Web Storage API this adapter uses. Both `sessionStorage`
|
|
191
|
+
* and `localStorage` fit.
|
|
192
|
+
*/
|
|
193
|
+
interface StorageLike {
|
|
194
|
+
getItem(key: string): string | null;
|
|
195
|
+
setItem(key: string, value: string): void;
|
|
196
|
+
}
|
|
197
|
+
/** A stored record: the serialized entry plus its generated UUID. */
|
|
198
|
+
interface WebStorageErrorRecord extends SerializedErrorLogEntry {
|
|
199
|
+
id: string;
|
|
200
|
+
}
|
|
201
|
+
interface WebStorageErrorOptions {
|
|
202
|
+
/** Key the entries are stored under, as one JSON array. Defaults to `error_log`. */
|
|
203
|
+
key?: string;
|
|
204
|
+
/** Most entries to keep. The oldest are dropped first. Defaults to `100`. */
|
|
205
|
+
maxEntries?: number;
|
|
206
|
+
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
207
|
+
prefix?: string;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Keeps the newest entries in a Web Storage object (`sessionStorage` or
|
|
211
|
+
* `localStorage`) as a JSON array under one key, capped at `maxEntries`.
|
|
212
|
+
* When the store is full, the oldest entries are dropped until the new one fits.
|
|
213
|
+
*/
|
|
214
|
+
declare class WebStorageErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
215
|
+
private readonly storage;
|
|
216
|
+
private readonly key;
|
|
217
|
+
private readonly maxEntries;
|
|
218
|
+
private readonly prefix;
|
|
219
|
+
/** @throws {RangeError} if `options.maxEntries` is not a positive integer. */
|
|
220
|
+
constructor(storage: StorageLike, options?: WebStorageErrorOptions);
|
|
221
|
+
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
222
|
+
/** Reads, appends, trims, and writes back. Runs without awaiting, so calls never interleave. */
|
|
223
|
+
private append;
|
|
224
|
+
/** Returns the stored records, or none if the value is missing or unreadable. */
|
|
225
|
+
private readRecords;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* The subset of `node:fs/promises` the file adapters use. Pass `fs.promises`
|
|
230
|
+
* (or `node:fs/promises`) yourself, or leave `fs` unset in Node and Bun.
|
|
231
|
+
*/
|
|
232
|
+
interface FileSystemLike {
|
|
233
|
+
appendFile(path: string, data: string): Promise<unknown>;
|
|
234
|
+
mkdir(path: string, options: {
|
|
235
|
+
recursive: true;
|
|
236
|
+
}): Promise<unknown>;
|
|
237
|
+
stat(path: string): Promise<{
|
|
238
|
+
size: number;
|
|
239
|
+
}>;
|
|
240
|
+
rename(from: string, to: string): Promise<unknown>;
|
|
241
|
+
rm(path: string, options: {
|
|
242
|
+
force: true;
|
|
243
|
+
}): Promise<unknown>;
|
|
244
|
+
}
|
|
245
|
+
/** `FileSystemLike` plus the reading and replacing that whole-file writes need. */
|
|
246
|
+
interface ReadWriteFileSystemLike extends FileSystemLike {
|
|
247
|
+
readFile(path: string, encoding: 'utf8'): Promise<string>;
|
|
248
|
+
writeFile(path: string, data: string): Promise<unknown>;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
interface FlatFileErrorOptions {
|
|
252
|
+
/** File system to write to. Defaults to `node:fs/promises`, loaded on first use. */
|
|
253
|
+
fs?: FileSystemLike;
|
|
254
|
+
/** Turns an entry into one line of text. Defaults to `formatErrorLogLine`. */
|
|
255
|
+
formatLine?: (entry: SerializedErrorLogEntry) => string;
|
|
256
|
+
/** Rotate the file before it would grow past this many bytes. Off by default. */
|
|
257
|
+
maxBytes?: number;
|
|
258
|
+
/** Rotated files to keep (`app.log.1` is newest). Defaults to `3`. Needs `maxBytes`. */
|
|
259
|
+
maxFiles?: number;
|
|
260
|
+
/** Create missing parent directories on first use. Defaults to `true`. */
|
|
261
|
+
createDirectory?: boolean;
|
|
262
|
+
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
263
|
+
prefix?: string;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* The default line format:
|
|
267
|
+
* `2026-01-02T03:04:05.000Z [CODE] source: message (cause: Error: details)`.
|
|
268
|
+
* `source` and `cause` are left out when the entry has none.
|
|
269
|
+
*/
|
|
270
|
+
declare function formatErrorLogLine(entry: SerializedErrorLogEntry): string;
|
|
271
|
+
/**
|
|
272
|
+
* Appends one text line per entry to a file, optionally rotating it by size.
|
|
273
|
+
* Writes are queued, so concurrent `log` calls never interleave or race a rotation.
|
|
274
|
+
*/
|
|
275
|
+
declare class FlatFileErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
276
|
+
private readonly filePath;
|
|
277
|
+
private readonly formatLine;
|
|
278
|
+
private readonly maxBytes;
|
|
279
|
+
private readonly maxFiles;
|
|
280
|
+
private readonly createDirectory;
|
|
281
|
+
private readonly prefix;
|
|
282
|
+
private fs;
|
|
283
|
+
private directoryReady;
|
|
284
|
+
private queue;
|
|
285
|
+
/** @throws {RangeError} if `maxBytes` or `maxFiles` is not a positive integer. */
|
|
286
|
+
constructor(filePath: string, options?: FlatFileErrorOptions);
|
|
287
|
+
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
288
|
+
private write;
|
|
289
|
+
/** Uses the injected file system, or loads `node:fs/promises` on first use. */
|
|
290
|
+
private getFileSystem;
|
|
291
|
+
private prepareDirectory;
|
|
292
|
+
/**
|
|
293
|
+
* Moves `app.log` to `app.log.1` (shifting older files up, dropping the
|
|
294
|
+
* oldest) when the next line would push it past `maxBytes`. A failed rotation
|
|
295
|
+
* is reported, but the entry is still written so it is not lost.
|
|
296
|
+
*/
|
|
297
|
+
private rotateIfNeeded;
|
|
298
|
+
private renameIfPresent;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/** A stored record: the serialized entry plus its generated UUID. */
|
|
302
|
+
interface JsonFileErrorRecord extends SerializedErrorLogEntry {
|
|
303
|
+
id: string;
|
|
304
|
+
}
|
|
305
|
+
interface JsonFileErrorOptions {
|
|
306
|
+
/**
|
|
307
|
+
* `ndjson` (default) appends one compact JSON object per line, which is cheap
|
|
308
|
+
* and safe to tail. `array` keeps the whole file as one JSON array that is
|
|
309
|
+
* rewritten on every entry.
|
|
310
|
+
*/
|
|
311
|
+
mode?: 'ndjson' | 'array';
|
|
312
|
+
/** Array mode only: most entries to keep. The oldest are dropped first. */
|
|
313
|
+
maxEntries?: number;
|
|
314
|
+
/** Array mode only: spaces of indentation. Defaults to `2`; `0` is compact. */
|
|
315
|
+
indent?: number;
|
|
316
|
+
/** File system to write to. Defaults to `node:fs/promises`, loaded on first use. */
|
|
317
|
+
fs?: ReadWriteFileSystemLike;
|
|
318
|
+
/** Create missing parent directories on first use. Defaults to `true`. */
|
|
319
|
+
createDirectory?: boolean;
|
|
320
|
+
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
321
|
+
prefix?: string;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Stores entries as JSON in a file (Node and Bun), either as newline-delimited
|
|
325
|
+
* JSON or as one array. Writes are queued, so concurrent `log` calls stay in
|
|
326
|
+
* order. Only one process should write to a given file.
|
|
327
|
+
*/
|
|
328
|
+
declare class JsonFileErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
329
|
+
private readonly filePath;
|
|
330
|
+
private readonly mode;
|
|
331
|
+
private readonly maxEntries;
|
|
332
|
+
private readonly indent;
|
|
333
|
+
private readonly createDirectory;
|
|
334
|
+
private readonly prefix;
|
|
335
|
+
private fs;
|
|
336
|
+
private directoryReady;
|
|
337
|
+
private queue;
|
|
338
|
+
/** @throws {RangeError} if `maxEntries` or `indent` is invalid, or `maxEntries` is used outside array mode. */
|
|
339
|
+
constructor(filePath: string, options?: JsonFileErrorOptions);
|
|
340
|
+
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
341
|
+
private write;
|
|
342
|
+
private getFileSystem;
|
|
343
|
+
private prepareDirectory;
|
|
344
|
+
/**
|
|
345
|
+
* Adds the record to the array and replaces the file. The new content is
|
|
346
|
+
* written to a temporary file first and renamed into place, so a crash
|
|
347
|
+
* mid-write cannot leave a half-written file.
|
|
348
|
+
*/
|
|
349
|
+
private rewriteArray;
|
|
350
|
+
/**
|
|
351
|
+
* Returns the records already in the file. A missing or empty file has none.
|
|
352
|
+
* A file that is not a JSON array is moved to `<path>.corrupt` (so nothing is
|
|
353
|
+
* lost) and logging continues with a fresh file.
|
|
354
|
+
*/
|
|
355
|
+
private readRecords;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
type SqlDialect = 'postgres' | 'mysql';
|
|
359
|
+
/**
|
|
360
|
+
* The only thing these adapters need from a database driver: run one
|
|
361
|
+
* parameterized statement. `pg` (`Pool` / `Client`) and `mysql2/promise`
|
|
362
|
+
* (`Pool` / `Connection`) both fit as they are.
|
|
363
|
+
*/
|
|
364
|
+
interface SqlClientLike {
|
|
365
|
+
query(sql: string, params: unknown[]): Promise<unknown>;
|
|
366
|
+
}
|
|
367
|
+
interface SqlErrorOptions {
|
|
368
|
+
/** Table to write to. Defaults to `error_log`. Letters, digits and `_` only, up to 47 characters. */
|
|
369
|
+
tableName?: string;
|
|
370
|
+
/** Create the table (and index) on first use. Defaults to `true`. */
|
|
371
|
+
createTable?: boolean;
|
|
372
|
+
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
373
|
+
prefix?: string;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Returns the statements that create the error log table and its index for a
|
|
377
|
+
* dialect. Use this to run your own migration when `createTable` is disabled.
|
|
378
|
+
*
|
|
379
|
+
* Postgres gets a native `UUID` key, `JSONB` for the cause, and `TIMESTAMPTZ`
|
|
380
|
+
* columns. MySQL gets a `CHAR(36)` UUID key (it has no UUID type), a `JSON`
|
|
381
|
+
* cause, and `DATETIME(3)` columns holding UTC times.
|
|
382
|
+
*/
|
|
383
|
+
declare function buildErrorLogTableDdl(dialect: SqlDialect, tableName?: string): string[];
|
|
384
|
+
/** Shared by the Postgres and MySQL adapters: only the SQL text and time format differ. */
|
|
385
|
+
declare abstract class SqlErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
386
|
+
private readonly client;
|
|
387
|
+
private readonly dialect;
|
|
388
|
+
private readonly adapterName;
|
|
389
|
+
private readonly tableName;
|
|
390
|
+
private readonly createTable;
|
|
391
|
+
private readonly prefix;
|
|
392
|
+
private tableReady;
|
|
393
|
+
protected constructor(client: SqlClientLike, dialect: SqlDialect, adapterName: string, options: SqlErrorOptions);
|
|
394
|
+
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
395
|
+
private insertSql;
|
|
396
|
+
/** Creates the table once. A failed attempt is retried on the next log call. */
|
|
397
|
+
private ensureTable;
|
|
398
|
+
private runCreateStatements;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Writes entries to Postgres. Pass a `pg` `Pool` or `Client`.
|
|
402
|
+
*
|
|
403
|
+
* ```ts
|
|
404
|
+
* const adapter = new PostgresErrorAdapter(new Pool({ connectionString }));
|
|
405
|
+
* ```
|
|
406
|
+
*/
|
|
407
|
+
declare class PostgresErrorAdapter<TCode extends string = string> extends SqlErrorAdapter<TCode> {
|
|
408
|
+
/** @throws {RangeError} if `options.tableName` is not a plain identifier of 47 characters or fewer. */
|
|
409
|
+
constructor(client: SqlClientLike, options?: SqlErrorOptions);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Writes entries to MySQL or MariaDB. Pass a `mysql2/promise` `Pool` or `Connection`.
|
|
413
|
+
*
|
|
414
|
+
* ```ts
|
|
415
|
+
* const adapter = new MySqlErrorAdapter(mysql.createPool(connectionUri));
|
|
416
|
+
* ```
|
|
417
|
+
*/
|
|
418
|
+
declare class MySqlErrorAdapter<TCode extends string = string> extends SqlErrorAdapter<TCode> {
|
|
419
|
+
/** @throws {RangeError} if `options.tableName` is not a plain identifier of 47 characters or fewer. */
|
|
420
|
+
constructor(client: SqlClientLike, options?: SqlErrorOptions);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* The only thing this adapter needs from a Redis client: send one raw command
|
|
425
|
+
* as an array of strings. node-redis (`client.sendCommand`) already matches.
|
|
426
|
+
* ioredis needs a one-line wrapper:
|
|
427
|
+
*
|
|
428
|
+
* ```ts
|
|
429
|
+
* const client: RedisClientLike = {
|
|
430
|
+
* sendCommand: (args) => redis.call(args[0] as string, ...args.slice(1)),
|
|
431
|
+
* };
|
|
432
|
+
* ```
|
|
433
|
+
*/
|
|
434
|
+
interface RedisClientLike {
|
|
435
|
+
sendCommand(args: string[]): Promise<unknown>;
|
|
436
|
+
}
|
|
437
|
+
interface RedisErrorOptions {
|
|
438
|
+
/**
|
|
439
|
+
* `list` (default) pushes each entry onto a Redis list as one JSON string.
|
|
440
|
+
* `stream` appends each entry to a Redis stream (`XADD`) as separate fields.
|
|
441
|
+
*/
|
|
442
|
+
mode?: 'list' | 'stream';
|
|
443
|
+
/** Key to write to. Defaults to `error_log`. */
|
|
444
|
+
key?: string;
|
|
445
|
+
/**
|
|
446
|
+
* Most entries to keep. The oldest are dropped first. Unlimited by default.
|
|
447
|
+
* Lists are trimmed with `LTRIM` after the push; streams use an exact `MAXLEN`.
|
|
448
|
+
*/
|
|
449
|
+
maxEntries?: number;
|
|
450
|
+
/**
|
|
451
|
+
* List mode only: which end to push onto. `right` (default, `RPUSH`) keeps
|
|
452
|
+
* the newest entry last; `left` (`LPUSH`) keeps the newest entry first.
|
|
453
|
+
*/
|
|
454
|
+
side?: 'left' | 'right';
|
|
455
|
+
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
456
|
+
prefix?: string;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Writes entries to Redis, either as a capped list of JSON strings or as a
|
|
460
|
+
* stream. Each record holds a UUID `id` plus the serialized entry. In stream
|
|
461
|
+
* mode `cause` and `source` fields are left out when the entry has none.
|
|
462
|
+
*/
|
|
463
|
+
declare class RedisErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
464
|
+
private readonly client;
|
|
465
|
+
private readonly mode;
|
|
466
|
+
private readonly key;
|
|
467
|
+
private readonly maxEntries;
|
|
468
|
+
private readonly side;
|
|
469
|
+
private readonly prefix;
|
|
470
|
+
/** @throws {RangeError} if `key` is empty, `maxEntries` is not a positive integer, or `mode` / `side` is unknown. */
|
|
471
|
+
constructor(client: RedisClientLike, options?: RedisErrorOptions);
|
|
472
|
+
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
473
|
+
private buildStreamCommand;
|
|
474
|
+
/**
|
|
475
|
+
* Drops the oldest list entries beyond `maxEntries`. The entry is already
|
|
476
|
+
* stored by now, so a trim failure is reported but does not fail the call;
|
|
477
|
+
* the next successful write trims the list again.
|
|
478
|
+
*/
|
|
479
|
+
private trimList;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/** The parameters this adapter passes to `putObject`. */
|
|
483
|
+
interface S3PutObjectInput {
|
|
484
|
+
Bucket: string;
|
|
485
|
+
Key: string;
|
|
486
|
+
Body: string;
|
|
487
|
+
ContentType: string;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* The only thing this adapter needs from an S3 client: `putObject`. The AWS
|
|
491
|
+
* SDK v3 aggregated client (`new S3({ ... })` from `@aws-sdk/client-s3`) fits as
|
|
492
|
+
* it is, and so does anything else that follows the S3 API, including
|
|
493
|
+
* DigitalOcean Spaces, Cloudflare R2 and MinIO when you point the client at
|
|
494
|
+
* their endpoint.
|
|
495
|
+
*/
|
|
496
|
+
interface S3ClientLike {
|
|
497
|
+
putObject(input: S3PutObjectInput): Promise<unknown>;
|
|
498
|
+
}
|
|
499
|
+
interface S3BatchOptions {
|
|
500
|
+
/** Upload once this many entries are buffered. */
|
|
501
|
+
batchSize: number;
|
|
502
|
+
/**
|
|
503
|
+
* Also upload when the oldest buffered entry has waited this long (ms). The
|
|
504
|
+
* timer does not keep the process alive, so call `flush()` before exiting.
|
|
505
|
+
*/
|
|
506
|
+
maxWaitMs?: number;
|
|
507
|
+
}
|
|
508
|
+
interface S3ErrorOptions {
|
|
509
|
+
/**
|
|
510
|
+
* Key prefix, for example `logs/app/`. A trailing slash is added if missing.
|
|
511
|
+
* Defaults to `error_log/`. Use `''` for no prefix.
|
|
512
|
+
*/
|
|
513
|
+
keyPrefix?: string;
|
|
514
|
+
/**
|
|
515
|
+
* Content type of the uploaded objects. Defaults to `application/json`, or
|
|
516
|
+
* `application/x-ndjson` when batching.
|
|
517
|
+
*/
|
|
518
|
+
contentType?: string;
|
|
519
|
+
/**
|
|
520
|
+
* Buffer entries and upload them together as one newline-delimited JSON
|
|
521
|
+
* object. Off by default: one object per entry.
|
|
522
|
+
*/
|
|
523
|
+
batch?: S3BatchOptions;
|
|
524
|
+
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
525
|
+
prefix?: string;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Stores entries as objects in an S3-compatible bucket, keyed by date and UUID:
|
|
529
|
+
* `error_log/2026/01/02/20260102T030405678Z-<uuid>.json`.
|
|
530
|
+
*
|
|
531
|
+
* By default each entry becomes its own JSON object and `log` resolves once the
|
|
532
|
+
* upload succeeds. With `batch`, entries are buffered and uploaded together as
|
|
533
|
+
* one `.ndjson` object; `log` then resolves ok as soon as the entry is
|
|
534
|
+
* buffered (it is not stored yet), except for the call that fills the batch,
|
|
535
|
+
* which resolves with the upload result. Call `flush()` before shutting down.
|
|
536
|
+
*/
|
|
537
|
+
declare class S3ErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
538
|
+
private readonly client;
|
|
539
|
+
private readonly bucket;
|
|
540
|
+
private readonly keyPrefix;
|
|
541
|
+
private readonly contentType;
|
|
542
|
+
private readonly batch;
|
|
543
|
+
private readonly logPrefix;
|
|
544
|
+
private buffer;
|
|
545
|
+
private timer;
|
|
546
|
+
private flushQueue;
|
|
547
|
+
/** @throws {RangeError} if `bucket` is empty or the batch options are invalid. */
|
|
548
|
+
constructor(client: S3ClientLike, bucket: string, options?: S3ErrorOptions);
|
|
549
|
+
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
550
|
+
/**
|
|
551
|
+
* Uploads any buffered entries now. Resolves ok when nothing is buffered.
|
|
552
|
+
* Entries from a failed upload stay buffered and are retried by the next flush.
|
|
553
|
+
*/
|
|
554
|
+
flush(): Promise<ErrorLogResult>;
|
|
555
|
+
private addToBatch;
|
|
556
|
+
private scheduleFlush;
|
|
557
|
+
private uploadBuffered;
|
|
558
|
+
private upload;
|
|
559
|
+
private fail;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export { type CollectionLike, CompositeErrorAdapter, ConsoleErrorAdapter, type ConsoleErrorOptions, type ErrorLogAdapter, type ErrorLogEntry, type ErrorLogResult, type FileSystemLike, FlatFileErrorAdapter, type FlatFileErrorOptions, type IdbDatabaseLike, type IdbObjectStoreLike, type IdbTransactionLike, type IdbUpgradeDatabaseLike, IndexedDbErrorAdapter, type IndexedDbErrorOptions, type IndexedDbErrorRecord, JsonFileErrorAdapter, type JsonFileErrorOptions, type JsonFileErrorRecord, MongoDbErrorAdapter, type MongoDbErrorOptions, MySqlErrorAdapter, PostgresErrorAdapter, type ReadWriteFileSystemLike, type RedisClientLike, RedisErrorAdapter, type RedisErrorOptions, type S3BatchOptions, type S3ClientLike, S3ErrorAdapter, type S3ErrorOptions, type S3PutObjectInput, type SerializedErrorLogEntry, type SqlClientLike, type SqlDialect, type SqlErrorOptions, type SqliteClientLike, SqliteErrorAdapter, type SqliteErrorOptions, type StorageLike, WebStorageErrorAdapter, type WebStorageErrorOptions, type WebStorageErrorRecord, WebhookErrorAdapter, type WebhookErrorOptions, buildCreateErrorLogTableSql, buildErrorLogTableDdl, createErrorLogStore, formatErrorLogLine, serializeCause, serializeEntry };
|