@richardmcquiston01/error-log-adapter 0.4.0 → 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/README.md +132 -13
- package/dist/index.cjs +650 -234
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +224 -22
- package/dist/index.d.ts +224 -22
- package/dist/index.mjs +649 -234
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,17 @@ interface ErrorLogEntry<TCode extends string = string> {
|
|
|
10
10
|
source?: string;
|
|
11
11
|
/** ISO 8601 timestamp. Adapters fill this in when it is omitted. */
|
|
12
12
|
timestamp?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Optional UUID that identifies this entry. Adapters generate a new one for
|
|
15
|
+
* every `log` call when it is omitted, so logging the same entry twice stores
|
|
16
|
+
* it twice. Supply the same `id` (and, for S3, the same `timestamp`) to make
|
|
17
|
+
* a retry safe: sinks that can detect a repeat overwrite or skip the existing
|
|
18
|
+
* record instead of adding another. It must be a UUID, for example from
|
|
19
|
+
* `crypto.randomUUID()`; anything else makes `log` return `ok: false`.
|
|
20
|
+
* Redis, the flat file and NDJSON file adapters, and the console cannot
|
|
21
|
+
* detect a repeat.
|
|
22
|
+
*/
|
|
23
|
+
id?: string;
|
|
13
24
|
}
|
|
14
25
|
/** Outcome of a `log` call. Callers should check `ok`. */
|
|
15
26
|
interface ErrorLogResult {
|
|
@@ -34,8 +45,16 @@ interface SerializedErrorLogEntry {
|
|
|
34
45
|
timestamp: string;
|
|
35
46
|
}
|
|
36
47
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
48
|
+
* Returns a copy of `cause` that `JSON.stringify` can always handle, so a
|
|
49
|
+
* strange cause can never stop an entry from being stored.
|
|
50
|
+
*
|
|
51
|
+
* - `Error` objects (including ones from another realm) become
|
|
52
|
+
* `{ name, message, stack }`, plus `cause` and, for an `AggregateError`,
|
|
53
|
+
* `errors`, which are converted the same way.
|
|
54
|
+
* - Circular references become `"[Circular]"`, and anything nested deeper than
|
|
55
|
+
* `MAX_CAUSE_DEPTH` levels becomes `"[Truncated]"`.
|
|
56
|
+
* - `BigInt`, `Symbol` and function values, and non-finite numbers, become strings.
|
|
57
|
+
* - A property or `toJSON` that throws is replaced by a short description.
|
|
39
58
|
*/
|
|
40
59
|
declare function serializeCause(cause: unknown): unknown;
|
|
41
60
|
/** Returns a JSON-safe copy of the entry, adding a timestamp if missing. */
|
|
@@ -56,13 +75,34 @@ interface WebhookErrorOptions {
|
|
|
56
75
|
headers?: Record<string, string>;
|
|
57
76
|
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
58
77
|
prefix?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Allow a plain `http://` URL. Entries contain error messages and stack
|
|
80
|
+
* traces, so they are only sent over `https://` unless this is `true`.
|
|
81
|
+
* `http://localhost`, `127.0.0.1` and `[::1]` are always allowed.
|
|
82
|
+
* Defaults to `false`.
|
|
83
|
+
*/
|
|
84
|
+
allowInsecure?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* How long to wait for the webhook to answer, in milliseconds. Defaults to
|
|
87
|
+
* 10000. Pass `Infinity` to wait without limit. When it passes, the request is
|
|
88
|
+
* cancelled, so the connection is closed rather than left open; the server may
|
|
89
|
+
* still have received the entry.
|
|
90
|
+
*/
|
|
91
|
+
timeoutMs?: number;
|
|
59
92
|
}
|
|
60
93
|
declare class WebhookErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
61
94
|
private readonly url;
|
|
62
95
|
private readonly options;
|
|
63
96
|
private readonly prefix;
|
|
97
|
+
private readonly timeoutMs;
|
|
98
|
+
/** Scheme and host only. Webhook URLs often carry a secret in the path or query. */
|
|
99
|
+
private readonly target;
|
|
100
|
+
/** @throws {RangeError} if `url` is not a valid `https://` URL (see `allowInsecure`) or `timeoutMs` is invalid. */
|
|
64
101
|
constructor(url: string, options?: WebhookErrorOptions);
|
|
65
102
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
103
|
+
private redirectMessage;
|
|
104
|
+
/** Replaces the full URL in a message with its origin, in case the runtime put it there. */
|
|
105
|
+
private redact;
|
|
66
106
|
private fail;
|
|
67
107
|
}
|
|
68
108
|
|
|
@@ -73,26 +113,63 @@ interface CollectionLike {
|
|
|
73
113
|
interface MongoDbErrorOptions {
|
|
74
114
|
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
75
115
|
prefix?: string;
|
|
116
|
+
/**
|
|
117
|
+
* How long `log` waits for the insert before giving up, in milliseconds. Defaults to
|
|
118
|
+
* 10000. Pass `Infinity` to wait without limit. The call cannot be cancelled,
|
|
119
|
+
* so it may still finish after `log` has returned a failure.
|
|
120
|
+
*/
|
|
121
|
+
timeoutMs?: number;
|
|
76
122
|
}
|
|
77
123
|
declare class MongoDbErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
78
124
|
private readonly collection;
|
|
79
125
|
private readonly prefix;
|
|
126
|
+
private readonly timeoutMs;
|
|
127
|
+
/** @throws {RangeError} if `options.timeoutMs` is not a positive number or Infinity. */
|
|
80
128
|
constructor(collection: CollectionLike, options?: MongoDbErrorOptions);
|
|
81
129
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
82
130
|
}
|
|
83
131
|
|
|
132
|
+
interface CompositeErrorOptions {
|
|
133
|
+
/**
|
|
134
|
+
* How long to wait for each adapter before reporting it as failed, in
|
|
135
|
+
* milliseconds. Defaults to 30000, longer than the 10000 default of the built-in
|
|
136
|
+
* adapters so their own, more specific timeout messages come first. This only
|
|
137
|
+
* matters for a custom adapter that can hang: one stuck adapter then cannot
|
|
138
|
+
* hold back the result of the others. Pass `Infinity` to wait without limit.
|
|
139
|
+
*/
|
|
140
|
+
timeoutMs?: number;
|
|
141
|
+
}
|
|
84
142
|
/** Sends every entry to several adapters. Succeeds only if all of them do. */
|
|
85
143
|
declare class CompositeErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
86
144
|
private readonly adapters;
|
|
87
|
-
|
|
145
|
+
private readonly timeoutMs;
|
|
146
|
+
/** @throws {RangeError} if `options.timeoutMs` is not a positive number or Infinity. */
|
|
147
|
+
constructor(adapters: ReadonlyArray<ErrorLogAdapter<TCode>>, options?: CompositeErrorOptions);
|
|
88
148
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
89
149
|
}
|
|
90
150
|
|
|
91
151
|
/** Event handler slot. Typed loosely so real DOM `IDBTransaction` objects fit. */
|
|
92
152
|
type IdbHandler = ((event: never) => unknown) | null;
|
|
153
|
+
/** The error object of a failed request or transaction (a `DOMException`). */
|
|
154
|
+
interface IdbErrorLike {
|
|
155
|
+
name?: string;
|
|
156
|
+
message?: string;
|
|
157
|
+
}
|
|
158
|
+
/** The subset of an `IDBRequest` this adapter uses. */
|
|
159
|
+
interface IdbRequestLike {
|
|
160
|
+
onerror: IdbHandler;
|
|
161
|
+
readonly error?: IdbErrorLike | null;
|
|
162
|
+
}
|
|
93
163
|
/** The subset of an `IDBObjectStore` this adapter uses. */
|
|
94
164
|
interface IdbObjectStoreLike {
|
|
165
|
+
/** Returns an `IDBRequest`. Fakes that return nothing also work. */
|
|
95
166
|
add(value: unknown): unknown;
|
|
167
|
+
/**
|
|
168
|
+
* Replaces the record with the same key. Used for entries that carry their own
|
|
169
|
+
* `id`, so logging one again does not fail on the existing key. A real
|
|
170
|
+
* `IDBObjectStore` has it; a fake without it falls back to `add`.
|
|
171
|
+
*/
|
|
172
|
+
put?(value: unknown): unknown;
|
|
96
173
|
}
|
|
97
174
|
/** The subset of an `IDBTransaction` this adapter uses. */
|
|
98
175
|
interface IdbTransactionLike {
|
|
@@ -100,9 +177,7 @@ interface IdbTransactionLike {
|
|
|
100
177
|
oncomplete: IdbHandler;
|
|
101
178
|
onerror: IdbHandler;
|
|
102
179
|
onabort: IdbHandler;
|
|
103
|
-
readonly error?:
|
|
104
|
-
message?: string;
|
|
105
|
-
} | null;
|
|
180
|
+
readonly error?: IdbErrorLike | null;
|
|
106
181
|
}
|
|
107
182
|
/** The subset of an `IDBDatabase` this adapter uses. */
|
|
108
183
|
interface IdbDatabaseLike {
|
|
@@ -128,6 +203,13 @@ interface IndexedDbErrorOptions {
|
|
|
128
203
|
storeName?: string;
|
|
129
204
|
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
130
205
|
prefix?: string;
|
|
206
|
+
/**
|
|
207
|
+
* How long `log` waits for the transaction to finish, in milliseconds. Defaults
|
|
208
|
+
* to 10000. Pass `Infinity` to wait without limit. A transaction can stay
|
|
209
|
+
* pending when a version change in another tab blocks it, or when the browser
|
|
210
|
+
* has evicted the origin's storage. The write may still finish afterwards.
|
|
211
|
+
*/
|
|
212
|
+
timeoutMs?: number;
|
|
131
213
|
}
|
|
132
214
|
/**
|
|
133
215
|
* Creates the error log object store (UUID `id` key, `timestamp` index).
|
|
@@ -138,9 +220,18 @@ declare class IndexedDbErrorAdapter<TCode extends string = string> implements Er
|
|
|
138
220
|
private readonly database;
|
|
139
221
|
private readonly storeName;
|
|
140
222
|
private readonly prefix;
|
|
223
|
+
private readonly timeoutMs;
|
|
224
|
+
/** @throws {RangeError} if `options.timeoutMs` is not a positive number or Infinity. */
|
|
141
225
|
constructor(database: IdbDatabaseLike, options?: IndexedDbErrorOptions);
|
|
142
226
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
143
|
-
/**
|
|
227
|
+
/**
|
|
228
|
+
* Resolves once the transaction commits; rejects if the request fails, the
|
|
229
|
+
* transaction aborts, or it does not finish within `timeoutMs`.
|
|
230
|
+
*
|
|
231
|
+
* Error events are handled here (`preventDefault` and `stopPropagation`), so a
|
|
232
|
+
* failed log write does not reach the `onerror` handler an app may have set on
|
|
233
|
+
* its own database object.
|
|
234
|
+
*/
|
|
144
235
|
private write;
|
|
145
236
|
}
|
|
146
237
|
|
|
@@ -166,6 +257,12 @@ interface SqliteErrorOptions {
|
|
|
166
257
|
createTable?: boolean;
|
|
167
258
|
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
168
259
|
prefix?: string;
|
|
260
|
+
/**
|
|
261
|
+
* How long `log` waits for the driver before giving up, in milliseconds. Defaults
|
|
262
|
+
* to 10000. Pass `Infinity` to wait without limit. The call cannot be
|
|
263
|
+
* cancelled, so it may still finish after `log` has returned a failure.
|
|
264
|
+
*/
|
|
265
|
+
timeoutMs?: number;
|
|
169
266
|
}
|
|
170
267
|
/**
|
|
171
268
|
* Returns the statements that create the error log table and its index.
|
|
@@ -177,13 +274,16 @@ declare class SqliteErrorAdapter<TCode extends string = string> implements Error
|
|
|
177
274
|
private readonly tableName;
|
|
178
275
|
private readonly createTable;
|
|
179
276
|
private readonly prefix;
|
|
277
|
+
private readonly timeoutMs;
|
|
180
278
|
private tableReady;
|
|
181
|
-
/** @throws {RangeError} if `options.tableName` is not a plain identifier. */
|
|
279
|
+
/** @throws {RangeError} if `options.tableName` is not a plain identifier or `options.timeoutMs` is invalid. */
|
|
182
280
|
constructor(client: SqliteClientLike, options?: SqliteErrorOptions);
|
|
183
281
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
184
282
|
/** Creates the table once. A failed attempt is retried on the next log call. */
|
|
185
283
|
private ensureTable;
|
|
186
284
|
private runCreateStatements;
|
|
285
|
+
/** Runs one statement, giving up waiting after `timeoutMs`. */
|
|
286
|
+
private run;
|
|
187
287
|
}
|
|
188
288
|
|
|
189
289
|
/**
|
|
@@ -194,6 +294,14 @@ interface StorageLike {
|
|
|
194
294
|
getItem(key: string): string | null;
|
|
195
295
|
setItem(key: string, value: string): void;
|
|
196
296
|
}
|
|
297
|
+
/**
|
|
298
|
+
* The part of `navigator.locks` this adapter uses. `localStorage` is shared by
|
|
299
|
+
* every tab of an origin and has no atomic update, so a lock keeps two tabs from
|
|
300
|
+
* overwriting each other's entry.
|
|
301
|
+
*/
|
|
302
|
+
interface LockManagerLike {
|
|
303
|
+
request<T>(name: string, callback: () => T | Promise<T>): Promise<T>;
|
|
304
|
+
}
|
|
197
305
|
/** A stored record: the serialized entry plus its generated UUID. */
|
|
198
306
|
interface WebStorageErrorRecord extends SerializedErrorLogEntry {
|
|
199
307
|
id: string;
|
|
@@ -205,24 +313,51 @@ interface WebStorageErrorOptions {
|
|
|
205
313
|
maxEntries?: number;
|
|
206
314
|
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
207
315
|
prefix?: string;
|
|
316
|
+
/**
|
|
317
|
+
* Lock manager that makes tabs sharing a `localStorage` take turns. Defaults to
|
|
318
|
+
* `navigator.locks` when the browser has it. This reduces lost entries but does
|
|
319
|
+
* not remove them: a tab in another process can still read a stale copy
|
|
320
|
+
* (measured in Chromium). Pass `null` to turn locking off.
|
|
321
|
+
*/
|
|
322
|
+
locks?: LockManagerLike | null;
|
|
208
323
|
}
|
|
209
324
|
/**
|
|
210
325
|
* Keeps the newest entries in a Web Storage object (`sessionStorage` or
|
|
211
326
|
* `localStorage`) as a JSON array under one key, capped at `maxEntries`.
|
|
212
327
|
* When the store is full, the oldest entries are dropped until the new one fits.
|
|
328
|
+
*
|
|
329
|
+
* `sessionStorage` belongs to one tab, so it is safe. `localStorage` is shared by
|
|
330
|
+
* every tab of the origin and has no atomic update: two tabs logging at the same
|
|
331
|
+
* moment can overwrite each other's entry while both get `ok: true`. In Chromium,
|
|
332
|
+
* tabs in separate processes (the usual case) even read a stale copy, so a lock
|
|
333
|
+
* reduces the loss without removing it. Where tabs may log at the same time and
|
|
334
|
+
* every entry matters, use `IndexedDbErrorAdapter`, whose writes are transactional.
|
|
213
335
|
*/
|
|
214
336
|
declare class WebStorageErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
215
337
|
private readonly storage;
|
|
216
338
|
private readonly key;
|
|
217
339
|
private readonly maxEntries;
|
|
218
340
|
private readonly prefix;
|
|
341
|
+
private readonly locks;
|
|
219
342
|
/** @throws {RangeError} if `options.maxEntries` is not a positive integer. */
|
|
220
343
|
constructor(storage: StorageLike, options?: WebStorageErrorOptions);
|
|
221
344
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
222
|
-
/**
|
|
345
|
+
/**
|
|
346
|
+
* Appends under a cross-tab lock when one is available. If the lock itself
|
|
347
|
+
* cannot be taken (for example a sandboxed frame), the entry is still written
|
|
348
|
+
* without it rather than lost.
|
|
349
|
+
*/
|
|
350
|
+
private appendLocked;
|
|
351
|
+
/** Reads, appends, trims, and writes back. Runs without awaiting, so calls in one tab never interleave. */
|
|
223
352
|
private append;
|
|
224
353
|
/** Returns the stored records, or none if the value is missing or unreadable. */
|
|
225
354
|
private readRecords;
|
|
355
|
+
/**
|
|
356
|
+
* Copies an unusable value to `<key>.corrupt` before it is replaced, so data
|
|
357
|
+
* the host app stored under the same key is not silently destroyed. Only the
|
|
358
|
+
* first one is kept; a later unusable value would not overwrite it.
|
|
359
|
+
*/
|
|
360
|
+
private setAside;
|
|
226
361
|
}
|
|
227
362
|
|
|
228
363
|
/**
|
|
@@ -281,7 +416,7 @@ declare class FlatFileErrorAdapter<TCode extends string = string> implements Err
|
|
|
281
416
|
private readonly prefix;
|
|
282
417
|
private fs;
|
|
283
418
|
private directoryReady;
|
|
284
|
-
private queue;
|
|
419
|
+
private readonly queue;
|
|
285
420
|
/** @throws {RangeError} if `maxBytes` or `maxFiles` is not a positive integer. */
|
|
286
421
|
constructor(filePath: string, options?: FlatFileErrorOptions);
|
|
287
422
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
@@ -334,7 +469,7 @@ declare class JsonFileErrorAdapter<TCode extends string = string> implements Err
|
|
|
334
469
|
private readonly prefix;
|
|
335
470
|
private fs;
|
|
336
471
|
private directoryReady;
|
|
337
|
-
private queue;
|
|
472
|
+
private readonly queue;
|
|
338
473
|
/** @throws {RangeError} if `maxEntries` or `indent` is invalid, or `maxEntries` is used outside array mode. */
|
|
339
474
|
constructor(filePath: string, options?: JsonFileErrorOptions);
|
|
340
475
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
@@ -371,6 +506,12 @@ interface SqlErrorOptions {
|
|
|
371
506
|
createTable?: boolean;
|
|
372
507
|
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
373
508
|
prefix?: string;
|
|
509
|
+
/**
|
|
510
|
+
* How long `log` waits for each database statement before giving up, in milliseconds. Defaults
|
|
511
|
+
* to 10000. Pass `Infinity` to wait without limit. The call cannot be
|
|
512
|
+
* cancelled, so it may still finish after `log` has returned a failure.
|
|
513
|
+
*/
|
|
514
|
+
timeoutMs?: number;
|
|
374
515
|
}
|
|
375
516
|
/**
|
|
376
517
|
* Returns the statements that create the error log table and its index for a
|
|
@@ -381,6 +522,12 @@ interface SqlErrorOptions {
|
|
|
381
522
|
* cause, and `DATETIME(3)` columns holding UTC times.
|
|
382
523
|
*/
|
|
383
524
|
declare function buildErrorLogTableDdl(dialect: SqlDialect, tableName?: string): string[];
|
|
525
|
+
/**
|
|
526
|
+
* Returns the statement that widens the `code` and `source` columns of a MySQL
|
|
527
|
+
* table created by `buildErrorLogTableDdl` in 0.4.0 or earlier, where they were
|
|
528
|
+
* `VARCHAR(255)` and a longer value made the insert fail. Run it once.
|
|
529
|
+
*/
|
|
530
|
+
declare function buildMySqlWidenColumnsSql(tableName?: string): string[];
|
|
384
531
|
/** Shared by the Postgres and MySQL adapters: only the SQL text and time format differ. */
|
|
385
532
|
declare abstract class SqlErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
386
533
|
private readonly client;
|
|
@@ -389,6 +536,7 @@ declare abstract class SqlErrorAdapter<TCode extends string = string> implements
|
|
|
389
536
|
private readonly tableName;
|
|
390
537
|
private readonly createTable;
|
|
391
538
|
private readonly prefix;
|
|
539
|
+
private readonly timeoutMs;
|
|
392
540
|
private tableReady;
|
|
393
541
|
protected constructor(client: SqlClientLike, dialect: SqlDialect, adapterName: string, options: SqlErrorOptions);
|
|
394
542
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
@@ -396,6 +544,8 @@ declare abstract class SqlErrorAdapter<TCode extends string = string> implements
|
|
|
396
544
|
/** Creates the table once. A failed attempt is retried on the next log call. */
|
|
397
545
|
private ensureTable;
|
|
398
546
|
private runCreateStatements;
|
|
547
|
+
/** Runs one statement, giving up waiting after `timeoutMs`. */
|
|
548
|
+
private query;
|
|
399
549
|
}
|
|
400
550
|
/**
|
|
401
551
|
* Writes entries to Postgres. Pass a `pg` `Pool` or `Client`.
|
|
@@ -454,6 +604,12 @@ interface RedisErrorOptions {
|
|
|
454
604
|
side?: 'left' | 'right';
|
|
455
605
|
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
456
606
|
prefix?: string;
|
|
607
|
+
/**
|
|
608
|
+
* How long `log` waits for each Redis command before giving up, in milliseconds. Defaults
|
|
609
|
+
* to 10000. Pass `Infinity` to wait without limit. The call cannot be
|
|
610
|
+
* cancelled, so it may still finish after `log` has returned a failure.
|
|
611
|
+
*/
|
|
612
|
+
timeoutMs?: number;
|
|
457
613
|
}
|
|
458
614
|
/**
|
|
459
615
|
* Writes entries to Redis, either as a capped list of JSON strings or as a
|
|
@@ -467,6 +623,7 @@ declare class RedisErrorAdapter<TCode extends string = string> implements ErrorL
|
|
|
467
623
|
private readonly maxEntries;
|
|
468
624
|
private readonly side;
|
|
469
625
|
private readonly prefix;
|
|
626
|
+
private readonly timeoutMs;
|
|
470
627
|
/** @throws {RangeError} if `key` is empty, `maxEntries` is not a positive integer, or `mode` / `side` is unknown. */
|
|
471
628
|
constructor(client: RedisClientLike, options?: RedisErrorOptions);
|
|
472
629
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
@@ -476,6 +633,8 @@ declare class RedisErrorAdapter<TCode extends string = string> implements ErrorL
|
|
|
476
633
|
* stored by now, so a trim failure is reported but does not fail the call;
|
|
477
634
|
* the next successful write trims the list again.
|
|
478
635
|
*/
|
|
636
|
+
/** Sends one command, giving up waiting after `timeoutMs`. */
|
|
637
|
+
private send;
|
|
479
638
|
private trimList;
|
|
480
639
|
}
|
|
481
640
|
|
|
@@ -528,6 +687,13 @@ interface S3ErrorOptions {
|
|
|
528
687
|
batch?: S3BatchOptions;
|
|
529
688
|
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
530
689
|
prefix?: string;
|
|
690
|
+
/**
|
|
691
|
+
* How long an upload may take before `log` (or `flush`) gives up waiting, in
|
|
692
|
+
* milliseconds. Defaults to 10000. Pass `Infinity` to wait without limit. The
|
|
693
|
+
* upload cannot be cancelled, so it may still finish afterwards; in batch mode
|
|
694
|
+
* the entries stay buffered and are uploaded again by the next flush.
|
|
695
|
+
*/
|
|
696
|
+
timeoutMs?: number;
|
|
531
697
|
}
|
|
532
698
|
/**
|
|
533
699
|
* Stores entries as objects in an S3-compatible bucket, keyed by date and UUID:
|
|
@@ -546,9 +712,10 @@ declare class S3ErrorAdapter<TCode extends string = string> implements ErrorLogA
|
|
|
546
712
|
private readonly contentType;
|
|
547
713
|
private readonly batch;
|
|
548
714
|
private readonly logPrefix;
|
|
715
|
+
private readonly timeoutMs;
|
|
549
716
|
private buffer;
|
|
550
717
|
private timer;
|
|
551
|
-
private flushQueue;
|
|
718
|
+
private readonly flushQueue;
|
|
552
719
|
/** @throws {RangeError} if `bucket` is empty or the batch options are invalid. */
|
|
553
720
|
constructor(client: S3ClientLike, bucket: string, options?: S3ErrorOptions);
|
|
554
721
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
@@ -604,11 +771,19 @@ interface FirestoreCollectionLike {
|
|
|
604
771
|
* ```ts
|
|
605
772
|
* const refLike: RealtimeDatabaseRefLike = {
|
|
606
773
|
* push: (value) => push(ref(db, 'error_log'), value),
|
|
774
|
+
* child: (key) => ({ set: (value) => set(ref(db, `error_log/${key}`), value) }),
|
|
607
775
|
* };
|
|
608
776
|
* ```
|
|
777
|
+
*
|
|
778
|
+
* `child(key).set(value)` is only needed for entries that carry their own `id`
|
|
779
|
+
* (see `ErrorLogEntry.id`): they are written under that key, so logging the same
|
|
780
|
+
* entry again overwrites the record instead of adding a second one.
|
|
609
781
|
*/
|
|
610
782
|
interface RealtimeDatabaseRefLike {
|
|
611
783
|
push(value: FirebaseErrorRecord): PromiseLike<unknown>;
|
|
784
|
+
child?(key: string): {
|
|
785
|
+
set(value: FirebaseErrorRecord): PromiseLike<unknown>;
|
|
786
|
+
};
|
|
612
787
|
}
|
|
613
788
|
interface FirebaseErrorOptions {
|
|
614
789
|
/**
|
|
@@ -618,7 +793,9 @@ interface FirebaseErrorOptions {
|
|
|
618
793
|
* The Firebase SDKs keep writes queued while the connection is down, and
|
|
619
794
|
* their promises stay pending until it returns, so without a limit `log`
|
|
620
795
|
* could hang for as long as an outage lasts. A write that timed out is still
|
|
621
|
-
* queued by the SDK and may be saved later.
|
|
796
|
+
* queued by the SDK and may be saved later. Retry a timeout only with the same
|
|
797
|
+
* `ErrorLogEntry.id`, so the retry overwrites the first write instead of
|
|
798
|
+
* adding a second one.
|
|
622
799
|
*/
|
|
623
800
|
timeoutMs?: number;
|
|
624
801
|
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
@@ -626,7 +803,11 @@ interface FirebaseErrorOptions {
|
|
|
626
803
|
}
|
|
627
804
|
/**
|
|
628
805
|
* Writes each entry as a document in a Firestore collection. The document id is
|
|
629
|
-
* the entry's UUID, so
|
|
806
|
+
* the entry's UUID, so the SDK finishing one queued write twice cannot create two
|
|
807
|
+
* documents. Calling `log` again without an `id` on the entry is a new write
|
|
808
|
+
* with a new UUID: if a call reported a timeout, the first write may still be
|
|
809
|
+
* saved later, and logging the same entry again can store it twice. Give the
|
|
810
|
+
* entry an `id` and the retry overwrites the same document.
|
|
630
811
|
*/
|
|
631
812
|
declare class FirestoreErrorAdapter<TCode extends string = string> implements ErrorLogAdapter<TCode> {
|
|
632
813
|
private readonly collection;
|
|
@@ -684,26 +865,46 @@ interface SupabaseClientLike {
|
|
|
684
865
|
};
|
|
685
866
|
}
|
|
686
867
|
interface SupabaseErrorOptions {
|
|
687
|
-
/** Table to write to. Defaults to `error_log`. */
|
|
868
|
+
/** Table to write to. Defaults to `error_log`. Letters, digits and `_` only. */
|
|
688
869
|
tableName?: string;
|
|
689
870
|
/** Text printed before failure messages. Defaults to `[error-log-adapter]`. */
|
|
690
871
|
prefix?: string;
|
|
872
|
+
/**
|
|
873
|
+
* How long `log` waits for Supabase to answer before giving up, in milliseconds. Defaults
|
|
874
|
+
* to 10000. Pass `Infinity` to wait without limit. The call cannot be
|
|
875
|
+
* cancelled, so it may still finish after `log` has returned a failure.
|
|
876
|
+
*/
|
|
877
|
+
timeoutMs?: number;
|
|
691
878
|
}
|
|
692
879
|
interface SupabaseSetupOptions {
|
|
693
880
|
/**
|
|
694
|
-
* Postgres roles allowed to insert, for example
|
|
695
|
-
*
|
|
696
|
-
*
|
|
881
|
+
* Postgres roles allowed to insert through the API, for example
|
|
882
|
+
* `['authenticated']`. Leave empty when only a server using the service role
|
|
883
|
+
* key logs: that role bypasses row level security, so it needs no policy, and
|
|
884
|
+
* its key must never be shipped to a browser.
|
|
885
|
+
*
|
|
886
|
+
* The generated policy only checks the size of each field. It does not tie a
|
|
887
|
+
* row to a user, so any holder of an allowed role's key can still add entries
|
|
888
|
+
* of their own making: forged entries can hide real incidents, and a flood of
|
|
889
|
+
* them uses up your database quota. Prefer `authenticated` over `anon`.
|
|
697
890
|
*/
|
|
698
891
|
insertRoles?: string[];
|
|
892
|
+
/**
|
|
893
|
+
* Required to allow `anon` (or `public`) to insert. The `anon` key is part of
|
|
894
|
+
* your frontend, so this lets anyone who loads the page write to the log.
|
|
895
|
+
* Defaults to `false`.
|
|
896
|
+
*/
|
|
897
|
+
allowPublicInsert?: boolean;
|
|
699
898
|
}
|
|
700
899
|
/**
|
|
701
900
|
* Returns the SQL to run once in the Supabase SQL editor: the error log table,
|
|
702
901
|
* with row level security turned on (as Supabase recommends for every table in
|
|
703
902
|
* an exposed schema) and, optionally, an insert-only policy for the given roles.
|
|
704
|
-
* Nobody but the service role can read
|
|
903
|
+
* The policy limits the size of each field. Nobody but the service role can read
|
|
904
|
+
* the log through the API.
|
|
705
905
|
*
|
|
706
|
-
* @throws {RangeError} if the table name or a role is not a plain identifier
|
|
906
|
+
* @throws {RangeError} if the table name or a role is not a plain identifier, or
|
|
907
|
+
* `anon` / `public` is listed without `allowPublicInsert: true`.
|
|
707
908
|
*/
|
|
708
909
|
declare function buildSupabaseSetupSql(tableName?: string, options?: SupabaseSetupOptions): string[];
|
|
709
910
|
/**
|
|
@@ -721,10 +922,11 @@ declare class SupabaseErrorAdapter<TCode extends string = string> implements Err
|
|
|
721
922
|
private readonly client;
|
|
722
923
|
private readonly tableName;
|
|
723
924
|
private readonly prefix;
|
|
724
|
-
|
|
925
|
+
private readonly timeoutMs;
|
|
926
|
+
/** @throws {RangeError} if `options.tableName` is not a plain identifier or `options.timeoutMs` is invalid. */
|
|
725
927
|
constructor(client: SupabaseClientLike, options?: SupabaseErrorOptions);
|
|
726
928
|
log(entry: ErrorLogEntry<TCode>): Promise<ErrorLogResult>;
|
|
727
929
|
private fail;
|
|
728
930
|
}
|
|
729
931
|
|
|
730
|
-
export { type CollectionLike, CompositeErrorAdapter, ConsoleErrorAdapter, type ConsoleErrorOptions, type ErrorLogAdapter, type ErrorLogEntry, type ErrorLogResult, type FileSystemLike, type FirebaseErrorOptions, type FirebaseErrorRecord, type FirestoreCollectionLike, FirestoreErrorAdapter, 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, RealtimeDatabaseErrorAdapter, type RealtimeDatabaseRefLike, 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, type SupabaseClientLike, SupabaseErrorAdapter, type SupabaseErrorLike, type SupabaseErrorOptions, type SupabaseErrorRow, type SupabaseInsertResult, type SupabaseSetupOptions, WebStorageErrorAdapter, type WebStorageErrorOptions, type WebStorageErrorRecord, WebhookErrorAdapter, type WebhookErrorOptions, buildCreateErrorLogTableSql, buildErrorLogTableDdl, buildSupabaseSetupSql, createErrorLogStore, formatErrorLogLine, serializeCause, serializeEntry };
|
|
932
|
+
export { type CollectionLike, CompositeErrorAdapter, type CompositeErrorOptions, ConsoleErrorAdapter, type ConsoleErrorOptions, type ErrorLogAdapter, type ErrorLogEntry, type ErrorLogResult, type FileSystemLike, type FirebaseErrorOptions, type FirebaseErrorRecord, type FirestoreCollectionLike, FirestoreErrorAdapter, FlatFileErrorAdapter, type FlatFileErrorOptions, type IdbDatabaseLike, type IdbObjectStoreLike, type IdbRequestLike, type IdbTransactionLike, type IdbUpgradeDatabaseLike, IndexedDbErrorAdapter, type IndexedDbErrorOptions, type IndexedDbErrorRecord, JsonFileErrorAdapter, type JsonFileErrorOptions, type JsonFileErrorRecord, type LockManagerLike, MongoDbErrorAdapter, type MongoDbErrorOptions, MySqlErrorAdapter, PostgresErrorAdapter, type ReadWriteFileSystemLike, RealtimeDatabaseErrorAdapter, type RealtimeDatabaseRefLike, 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, type SupabaseClientLike, SupabaseErrorAdapter, type SupabaseErrorLike, type SupabaseErrorOptions, type SupabaseErrorRow, type SupabaseInsertResult, type SupabaseSetupOptions, WebStorageErrorAdapter, type WebStorageErrorOptions, type WebStorageErrorRecord, WebhookErrorAdapter, type WebhookErrorOptions, buildCreateErrorLogTableSql, buildErrorLogTableDdl, buildMySqlWidenColumnsSql, buildSupabaseSetupSql, createErrorLogStore, formatErrorLogLine, serializeCause, serializeEntry };
|