@spinajs/log-common 2.0.480 → 2.0.482

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.
Files changed (68) hide show
  1. package/README.md +125 -4
  2. package/lib/cjs/BatchQueue.d.ts +127 -0
  3. package/lib/cjs/BatchQueue.d.ts.map +1 -0
  4. package/lib/cjs/BatchQueue.js +126 -0
  5. package/lib/cjs/BatchQueue.js.map +1 -0
  6. package/lib/cjs/filters/filter.d.ts +27 -0
  7. package/lib/cjs/filters/filter.d.ts.map +1 -0
  8. package/lib/cjs/filters/filter.js +20 -0
  9. package/lib/cjs/filters/filter.js.map +1 -0
  10. package/lib/cjs/filters/whenRepeated.d.ts +52 -0
  11. package/lib/cjs/filters/whenRepeated.d.ts.map +1 -0
  12. package/lib/cjs/filters/whenRepeated.js +98 -0
  13. package/lib/cjs/filters/whenRepeated.js.map +1 -0
  14. package/lib/cjs/format.d.ts +20 -0
  15. package/lib/cjs/format.d.ts.map +1 -0
  16. package/lib/cjs/format.js +75 -0
  17. package/lib/cjs/format.js.map +1 -0
  18. package/lib/cjs/index.d.ts +260 -21
  19. package/lib/cjs/index.d.ts.map +1 -1
  20. package/lib/cjs/index.js +207 -33
  21. package/lib/cjs/index.js.map +1 -1
  22. package/lib/cjs/perf.d.ts +109 -0
  23. package/lib/cjs/perf.d.ts.map +1 -0
  24. package/lib/cjs/perf.js +162 -0
  25. package/lib/cjs/perf.js.map +1 -0
  26. package/lib/cjs/persistence.d.ts +19 -0
  27. package/lib/cjs/persistence.d.ts.map +1 -0
  28. package/lib/cjs/persistence.js +137 -0
  29. package/lib/cjs/persistence.js.map +1 -0
  30. package/lib/cjs/serializers.d.ts +77 -0
  31. package/lib/cjs/serializers.d.ts.map +1 -0
  32. package/lib/cjs/serializers.js +215 -0
  33. package/lib/cjs/serializers.js.map +1 -0
  34. package/lib/mjs/BatchQueue.d.ts +127 -0
  35. package/lib/mjs/BatchQueue.d.ts.map +1 -0
  36. package/lib/mjs/BatchQueue.js +122 -0
  37. package/lib/mjs/BatchQueue.js.map +1 -0
  38. package/lib/mjs/filters/filter.d.ts +27 -0
  39. package/lib/mjs/filters/filter.d.ts.map +1 -0
  40. package/lib/mjs/filters/filter.js +16 -0
  41. package/lib/mjs/filters/filter.js.map +1 -0
  42. package/lib/mjs/filters/whenRepeated.d.ts +52 -0
  43. package/lib/mjs/filters/whenRepeated.d.ts.map +1 -0
  44. package/lib/mjs/filters/whenRepeated.js +95 -0
  45. package/lib/mjs/filters/whenRepeated.js.map +1 -0
  46. package/lib/mjs/format.d.ts +20 -0
  47. package/lib/mjs/format.d.ts.map +1 -0
  48. package/lib/mjs/format.js +72 -0
  49. package/lib/mjs/format.js.map +1 -0
  50. package/lib/mjs/index.d.ts +260 -21
  51. package/lib/mjs/index.d.ts.map +1 -1
  52. package/lib/mjs/index.js +201 -10
  53. package/lib/mjs/index.js.map +1 -1
  54. package/lib/mjs/perf.d.ts +109 -0
  55. package/lib/mjs/perf.d.ts.map +1 -0
  56. package/lib/mjs/perf.js +157 -0
  57. package/lib/mjs/perf.js.map +1 -0
  58. package/lib/mjs/persistence.d.ts +19 -0
  59. package/lib/mjs/persistence.d.ts.map +1 -0
  60. package/lib/mjs/persistence.js +132 -0
  61. package/lib/mjs/persistence.js.map +1 -0
  62. package/lib/mjs/serializers.d.ts +77 -0
  63. package/lib/mjs/serializers.d.ts.map +1 -0
  64. package/lib/mjs/serializers.js +208 -0
  65. package/lib/mjs/serializers.js.map +1 -0
  66. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  67. package/lib/tsconfig.mjs.tsbuildinfo +1 -1
  68. package/package.json +8 -9
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.persistLevel = persistLevel;
4
+ exports.readPersistedLevel = readPersistedLevel;
5
+ exports.clearPersistedLevel = clearPersistedLevel;
6
+ /**
7
+ * Browser-only runtime log-level persistence ( loglevel-style ). Lets a user's
8
+ * `setLevel(...)` choice survive page reloads via `localStorage`, with a
9
+ * `document.cookie` fallback for environments where storage throws ( eg. Safari
10
+ * private mode ). On Node ( no `window` ) every helper is a clean no-op.
11
+ *
12
+ * Kept dependency-free and free of any `node:*` imports so log-common stays
13
+ * browser-safe: the only globals touched are `window` / `document`, guarded by
14
+ * `typeof` checks.
15
+ */
16
+ const KEY_PREFIX = "spinajs:log:level:";
17
+ function storageKey(loggerName) {
18
+ return `${KEY_PREFIX}${loggerName}`;
19
+ }
20
+ /** True only in a browser-like environment with a usable localStorage. */
21
+ function hasWindow() {
22
+ return typeof window !== "undefined";
23
+ }
24
+ function writeCookie(key, value) {
25
+ if (typeof document === "undefined") {
26
+ return;
27
+ }
28
+ try {
29
+ // 1 year, path=/ so the value is visible across the app.
30
+ const maxAge = 60 * 60 * 24 * 365;
31
+ document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(value)};path=/;max-age=${maxAge}`;
32
+ }
33
+ catch {
34
+ // nothing else we can do - persistence is best-effort.
35
+ }
36
+ }
37
+ function readCookie(key) {
38
+ if (typeof document === "undefined") {
39
+ return undefined;
40
+ }
41
+ try {
42
+ const enc = encodeURIComponent(key);
43
+ const parts = document.cookie ? document.cookie.split(";") : [];
44
+ for (const part of parts) {
45
+ const [k, ...rest] = part.trim().split("=");
46
+ if (k === enc) {
47
+ return decodeURIComponent(rest.join("="));
48
+ }
49
+ }
50
+ }
51
+ catch {
52
+ // ignore
53
+ }
54
+ return undefined;
55
+ }
56
+ function expireCookie(key) {
57
+ if (typeof document === "undefined") {
58
+ return;
59
+ }
60
+ try {
61
+ document.cookie = `${encodeURIComponent(key)}=;path=/;max-age=0`;
62
+ }
63
+ catch {
64
+ // ignore
65
+ }
66
+ }
67
+ /**
68
+ * Persist `level` for `loggerName`. Browser only - writes `String(level)` to
69
+ * localStorage under `spinajs:log:level:<loggerName>`, falling back to a cookie
70
+ * when storage throws. No-op on Node.
71
+ */
72
+ function persistLevel(loggerName, level) {
73
+ if (!hasWindow()) {
74
+ return;
75
+ }
76
+ const key = storageKey(loggerName);
77
+ const value = String(level);
78
+ try {
79
+ // window.localStorage access itself can throw ( disabled cookies / private mode ).
80
+ if (window.localStorage) {
81
+ window.localStorage.setItem(key, value);
82
+ return;
83
+ }
84
+ }
85
+ catch {
86
+ // fall through to the cookie fallback below.
87
+ }
88
+ writeCookie(key, value);
89
+ }
90
+ /**
91
+ * Read back the persisted level for `loggerName` ( localStorage then cookie ).
92
+ * Returns a finite {@link LogLevel} number, or `undefined` when nothing valid is
93
+ * stored. Always `undefined` on Node.
94
+ */
95
+ function readPersistedLevel(loggerName) {
96
+ if (!hasWindow()) {
97
+ return undefined;
98
+ }
99
+ const key = storageKey(loggerName);
100
+ let raw;
101
+ try {
102
+ if (window.localStorage) {
103
+ raw = window.localStorage.getItem(key);
104
+ }
105
+ }
106
+ catch {
107
+ raw = undefined;
108
+ }
109
+ if (raw === null || raw === undefined) {
110
+ raw = readCookie(key);
111
+ }
112
+ if (raw === null || raw === undefined || raw === "") {
113
+ return undefined;
114
+ }
115
+ const parsed = Number(raw);
116
+ return Number.isFinite(parsed) ? parsed : undefined;
117
+ }
118
+ /**
119
+ * Remove any persisted level for `loggerName` ( localStorage + cookie ). No-op
120
+ * on Node.
121
+ */
122
+ function clearPersistedLevel(loggerName) {
123
+ if (!hasWindow()) {
124
+ return;
125
+ }
126
+ const key = storageKey(loggerName);
127
+ try {
128
+ if (window.localStorage) {
129
+ window.localStorage.removeItem(key);
130
+ }
131
+ }
132
+ catch {
133
+ // ignore - fall through to also expire the cookie.
134
+ }
135
+ expireCookie(key);
136
+ }
137
+ //# sourceMappingURL=persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../src/persistence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Pure, dependency-free serialization helpers used by the log targets.
3
+ *
4
+ * These functions are intentionally browser-safe: they use no Node-only APIs
5
+ * ( no `util`, no `Buffer` ), only plain ECMAScript. They are also written to
6
+ * be defensive - neither of them may ever throw, because a logger that crashes
7
+ * while trying to log an error is worse than useless.
8
+ */
9
+ /**
10
+ * Structured representation of an Error suitable for JSON serialization.
11
+ */
12
+ export interface ISerializedError {
13
+ name: string;
14
+ message: string;
15
+ stack?: string;
16
+ code?: string | number;
17
+ signal?: string;
18
+ }
19
+ /**
20
+ * Turn an `Error` into a plain, JSON-friendly record.
21
+ *
22
+ * - Returns `undefined` for anything that is not an `Error` ( callers only
23
+ * serialize actual errors ).
24
+ * - `stack` walks the `.cause` chain and any `AggregateError.errors`, appending
25
+ * each nested error under a `Caused by:` line ( bunyan-style ).
26
+ * - `code` / `signal` are included only when present ( common on Node system
27
+ * errors such as `ECONNREFUSED` / `SIGTERM` ).
28
+ * - Never throws.
29
+ */
30
+ export declare function serializeError(err: unknown): ISerializedError | undefined;
31
+ /**
32
+ * A serializer turns a raw log-variable value into a structured, log-friendly
33
+ * form. It receives the value stored under a given field name and returns its
34
+ * replacement. Returning `undefined` means "leave the original value alone"
35
+ * ( e.g. `serializeError` returns `undefined` for a non-Error ).
36
+ */
37
+ export type LogSerializer = (value: unknown) => unknown;
38
+ /**
39
+ * Registry of field-name -> serializer. Applied by {@link applySerializers} to
40
+ * every log entry's variables. Out of the box the SpinaJS `error` variable
41
+ * ( set by `createLogMessageObject` ) is serialized by {@link serializeError },
42
+ * so `error` becomes a plain `{ name, message, stack, code, signal }` record
43
+ * instead of an opaque `Error`.
44
+ */
45
+ export declare const serializers: Map<string, LogSerializer>;
46
+ /**
47
+ * Register ( or override ) the serializer used for a given log-variable field.
48
+ */
49
+ export declare function registerSerializer(field: string, fn: LogSerializer): void;
50
+ /**
51
+ * Apply the registered serializers to a log entry's variables, MUTATING `vars`
52
+ * in place.
53
+ *
54
+ * For each registered `[field, fn]`:
55
+ * - skip when `field` is absent or its value is `undefined` / `null`;
56
+ * - run `fn` inside a try/catch:
57
+ * - on success, overwrite `vars[field]` ONLY when the serializer returned
58
+ * a defined value, so a serializer that returns `undefined` for an
59
+ * unhandled value ( like `serializeError` on a non-Error ) leaves the
60
+ * original untouched;
61
+ * - on throw, replace the value with `{ serializerError: <message> }` so a
62
+ * broken serializer degrades gracefully and NEVER crashes the caller.
63
+ */
64
+ export declare function applySerializers(vars: Record<string, unknown>): void;
65
+ /**
66
+ * JSON-stringify any value without ever throwing.
67
+ *
68
+ * Three tiers:
69
+ * 1. plain `JSON.stringify` ( the common, fast path );
70
+ * 2. on throw ( typically circular references ) retry with a replacer that
71
+ * swaps already-seen objects for the string `"[Circular]"`, producing
72
+ * VALID JSON;
73
+ * 3. if that still throws ( e.g. a getter that throws while enumerating ),
74
+ * fall back to `String(value)`.
75
+ */
76
+ export declare function safeStringify(value: unknown, indent?: number): string;
77
+ //# sourceMappingURL=serializers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializers.d.ts","sourceRoot":"","sources":["../../src/serializers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA8ED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAiCzE;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;AAExD;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,4BAA+E,CAAC;AAExG;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,aAAa,GAAG,IAAI,CAEzE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAoBpE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CA4BrE"}
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ /**
3
+ * Pure, dependency-free serialization helpers used by the log targets.
4
+ *
5
+ * These functions are intentionally browser-safe: they use no Node-only APIs
6
+ * ( no `util`, no `Buffer` ), only plain ECMAScript. They are also written to
7
+ * be defensive - neither of them may ever throw, because a logger that crashes
8
+ * while trying to log an error is worse than useless.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.serializers = void 0;
12
+ exports.serializeError = serializeError;
13
+ exports.registerSerializer = registerSerializer;
14
+ exports.applySerializers = applySerializers;
15
+ exports.safeStringify = safeStringify;
16
+ /**
17
+ * Max depth we walk down the `.cause` chain. A self-referential cause
18
+ * ( `err.cause = err` ) would otherwise loop forever, so we cap the walk.
19
+ */
20
+ const MAX_CAUSE_DEPTH = 10;
21
+ /**
22
+ * Best-effort read of a property that might be defined via a throwing getter.
23
+ * Returns `undefined` instead of propagating the throw.
24
+ */
25
+ function safeGet(obj, key) {
26
+ try {
27
+ return obj[key];
28
+ }
29
+ catch {
30
+ return undefined;
31
+ }
32
+ }
33
+ /**
34
+ * Returns the most useful string form of an error for embedding in a stack:
35
+ * its `.stack` when available, otherwise its `.message`, otherwise `String()`.
36
+ */
37
+ function errorText(err) {
38
+ const stack = safeGet(err, "stack");
39
+ if (typeof stack === "string" && stack.length > 0) {
40
+ return stack;
41
+ }
42
+ const message = safeGet(err, "message");
43
+ if (typeof message === "string" && message.length > 0) {
44
+ return message;
45
+ }
46
+ try {
47
+ return String(err);
48
+ }
49
+ catch {
50
+ return "[unserializable error]";
51
+ }
52
+ }
53
+ /**
54
+ * Builds a combined stack string that walks the `.cause` chain and, for
55
+ * `AggregateError`, its inner `errors`. Mirrors bunyan's `getFullErrorStack`:
56
+ * each nested error is appended under a `Caused by:` line.
57
+ *
58
+ * `seen` guards against cycles ( shared cause objects ) and `depth` caps how
59
+ * far down the chain we recurse, so a self-referential cause cannot hang.
60
+ */
61
+ function buildFullStack(err, seen, depth) {
62
+ let out = errorText(err);
63
+ if (depth >= MAX_CAUSE_DEPTH || seen.has(err)) {
64
+ return out;
65
+ }
66
+ seen.add(err);
67
+ // Follow the standard `.cause` chain ( ES2022 error cause ).
68
+ const cause = safeGet(err, "cause");
69
+ if (cause instanceof Error && !seen.has(cause)) {
70
+ out += "\nCaused by: " + buildFullStack(cause, seen, depth + 1);
71
+ }
72
+ // AggregateError ( or any error carrying an `errors` array ) - surface each
73
+ // inner error under the same `Caused by:` style.
74
+ const errors = safeGet(err, "errors");
75
+ if (Array.isArray(errors)) {
76
+ for (const inner of errors) {
77
+ if (inner instanceof Error && !seen.has(inner)) {
78
+ out += "\nCaused by: " + buildFullStack(inner, seen, depth + 1);
79
+ }
80
+ }
81
+ }
82
+ return out;
83
+ }
84
+ /**
85
+ * Turn an `Error` into a plain, JSON-friendly record.
86
+ *
87
+ * - Returns `undefined` for anything that is not an `Error` ( callers only
88
+ * serialize actual errors ).
89
+ * - `stack` walks the `.cause` chain and any `AggregateError.errors`, appending
90
+ * each nested error under a `Caused by:` line ( bunyan-style ).
91
+ * - `code` / `signal` are included only when present ( common on Node system
92
+ * errors such as `ECONNREFUSED` / `SIGTERM` ).
93
+ * - Never throws.
94
+ */
95
+ function serializeError(err) {
96
+ if (!(err instanceof Error)) {
97
+ return undefined;
98
+ }
99
+ try {
100
+ const name = typeof err.name === "string" ? err.name : "Error";
101
+ const message = typeof err.message === "string" ? err.message : "";
102
+ const result = { name, message };
103
+ const stack = buildFullStack(err, new Set(), 0);
104
+ if (stack.length > 0) {
105
+ result.stack = stack;
106
+ }
107
+ // Node system errors carry a `code` ( e.g. 'ECONNREFUSED' ) and sometimes a
108
+ // `signal` ( e.g. 'SIGTERM' ). Include them only when actually present.
109
+ const code = safeGet(err, "code");
110
+ if (typeof code === "string" || typeof code === "number") {
111
+ result.code = code;
112
+ }
113
+ const signal = safeGet(err, "signal");
114
+ if (typeof signal === "string") {
115
+ result.signal = signal;
116
+ }
117
+ return result;
118
+ }
119
+ catch {
120
+ // Absolute last-resort guard - serialization must never throw.
121
+ return { name: "Error", message: "[unserializable error]" };
122
+ }
123
+ }
124
+ /**
125
+ * Registry of field-name -> serializer. Applied by {@link applySerializers} to
126
+ * every log entry's variables. Out of the box the SpinaJS `error` variable
127
+ * ( set by `createLogMessageObject` ) is serialized by {@link serializeError },
128
+ * so `error` becomes a plain `{ name, message, stack, code, signal }` record
129
+ * instead of an opaque `Error`.
130
+ */
131
+ exports.serializers = new Map([["error", serializeError]]);
132
+ /**
133
+ * Register ( or override ) the serializer used for a given log-variable field.
134
+ */
135
+ function registerSerializer(field, fn) {
136
+ exports.serializers.set(field, fn);
137
+ }
138
+ /**
139
+ * Apply the registered serializers to a log entry's variables, MUTATING `vars`
140
+ * in place.
141
+ *
142
+ * For each registered `[field, fn]`:
143
+ * - skip when `field` is absent or its value is `undefined` / `null`;
144
+ * - run `fn` inside a try/catch:
145
+ * - on success, overwrite `vars[field]` ONLY when the serializer returned
146
+ * a defined value, so a serializer that returns `undefined` for an
147
+ * unhandled value ( like `serializeError` on a non-Error ) leaves the
148
+ * original untouched;
149
+ * - on throw, replace the value with `{ serializerError: <message> }` so a
150
+ * broken serializer degrades gracefully and NEVER crashes the caller.
151
+ */
152
+ function applySerializers(vars) {
153
+ for (const [field, fn] of exports.serializers) {
154
+ if (!(field in vars)) {
155
+ continue;
156
+ }
157
+ const value = vars[field];
158
+ if (value === undefined || value === null) {
159
+ continue;
160
+ }
161
+ try {
162
+ const s = fn(value);
163
+ if (s !== undefined) {
164
+ vars[field] = s;
165
+ }
166
+ }
167
+ catch (e) {
168
+ vars[field] = { serializerError: e?.message ?? String(e) };
169
+ }
170
+ }
171
+ }
172
+ /**
173
+ * JSON-stringify any value without ever throwing.
174
+ *
175
+ * Three tiers:
176
+ * 1. plain `JSON.stringify` ( the common, fast path );
177
+ * 2. on throw ( typically circular references ) retry with a replacer that
178
+ * swaps already-seen objects for the string `"[Circular]"`, producing
179
+ * VALID JSON;
180
+ * 3. if that still throws ( e.g. a getter that throws while enumerating ),
181
+ * fall back to `String(value)`.
182
+ */
183
+ function safeStringify(value, indent) {
184
+ try {
185
+ // Tier 1: the fast, common path.
186
+ return JSON.stringify(value, undefined, indent);
187
+ }
188
+ catch {
189
+ // Tier 2: handle circular references with a WeakSet of seen objects.
190
+ try {
191
+ const seen = new WeakSet();
192
+ const replacer = (_key, val) => {
193
+ if (val !== null && typeof val === "object") {
194
+ if (seen.has(val)) {
195
+ return "[Circular]";
196
+ }
197
+ seen.add(val);
198
+ }
199
+ return val;
200
+ };
201
+ return JSON.stringify(value, replacer, indent);
202
+ }
203
+ catch {
204
+ // Tier 3: something else threw ( e.g. a throwing getter ). Give up on
205
+ // structured output but still return *a* string.
206
+ try {
207
+ return String(value);
208
+ }
209
+ catch {
210
+ return "[unserializable value]";
211
+ }
212
+ }
213
+ }
214
+ }
215
+ //# sourceMappingURL=serializers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializers.js","sourceRoot":"","sources":["../../src/serializers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * A small, dependency-free, browser-safe buffered-batch queue.
3
+ *
4
+ * `BatchQueue<T>` owns ACCUMULATION and FLUSH TRIGGERING only; it delegates the
5
+ * actual I/O to the owner via `onFlush`. Ported from the essence of
6
+ * OpenTelemetry's BatchLogRecordProcessor.
7
+ *
8
+ * Triggers a flush when either:
9
+ * - the buffer reaches `maxBatch` items ( size trigger ), or
10
+ * - the periodic timer fires every `flushIntervalMs` ( interval trigger ).
11
+ *
12
+ * ## Failure model
13
+ *
14
+ * There are two, deliberately distinct, ways items can leave the queue:
15
+ *
16
+ * 1. **Overflow ( the ONLY silent drop ).** The buffer is hard-capped at
17
+ * `maxQueue`. When it grows past the cap the OLDEST items are dropped so
18
+ * memory stays bounded, and `onOverflow(droppedItems)` fires. This is the
19
+ * back-pressure release valve for a stuck/slow sink.
20
+ *
21
+ * 2. **Flush failure ( never a silent drop ).** `onFlush` may throw / reject.
22
+ * `BatchQueue` does NOT retry, requeue, or swallow the batch on its own —
23
+ * that is the owner's decision. The rejection PROPAGATES to any caller that
24
+ * awaits `flush()` / `forceFlush()`, so the owner can `catch` it and call
25
+ * `requeueFront(batch)` to put the batch back at the front ( never-drop
26
+ * semantics ) or drop it deliberately. The periodic timer intentionally
27
+ * ignores the rejection ( `void this.flush()` ) so a failing sink never
28
+ * kills the flush loop; the in-flight guard is always cleared in `finally`
29
+ * so the next flush can proceed regardless of outcome.
30
+ *
31
+ * ## Re-entrancy
32
+ *
33
+ * At most one `onFlush` runs at a time. If a flush is already in flight, calling
34
+ * `flush()` returns the SAME in-flight promise ( coalesced ) rather than
35
+ * starting a second `onFlush`. A flush snapshots and clears the buffer
36
+ * synchronously before awaiting the I/O, so items enqueued during a flush land
37
+ * in a fresh buffer and are picked up by the next flush.
38
+ *
39
+ * ## Runtime
40
+ *
41
+ * Uses only `setInterval` / `setTimeout` ( available in both Node and browsers ).
42
+ * The periodic timer ( and the optional per-flush timeout timer ) are `unref()`'d
43
+ * when that method exists, so they never keep a Node process alive; the `?.`
44
+ * guard makes the calls harmless in browsers.
45
+ */
46
+ export interface IBatchQueueOptions<T> {
47
+ /** Flush automatically once the buffer reaches this many items. */
48
+ maxBatch: number;
49
+ /** Hard cap on buffered items. Beyond it the OLDEST are dropped ( onOverflow fires ). */
50
+ maxQueue: number;
51
+ /** Periodic flush tick in ms. The timer is unref()'d so it never blocks process exit. */
52
+ flushIntervalMs: number;
53
+ /** Optional per-flush timeout in ms. If onFlush does not settle in time, the flush rejects. */
54
+ exportTimeoutMs?: number;
55
+ /** Does the actual I/O for a batch. May throw/reject; the owner handles retry/requeue/drop. */
56
+ onFlush: (items: T[]) => Promise<void>;
57
+ /**
58
+ * Called when the queue cap is exceeded and the oldest items are dropped.
59
+ * Receives the DROPPED ITEMS themselves ( oldest first ) so an owner can route
60
+ * exactly what was dropped to a fallback ( see LogTarget.OnDropped ). Use
61
+ * `droppedItems.length` when only the count matters.
62
+ */
63
+ onOverflow?: (droppedItems: T[]) => void;
64
+ }
65
+ export declare class BatchQueue<T> {
66
+ private options;
67
+ private buffer;
68
+ private timer;
69
+ private stopped;
70
+ /**
71
+ * The currently running flush, or null when idle. Used both as the
72
+ * re-entrancy guard ( coalesce concurrent flush() calls ) and to let
73
+ * forceFlush()/shutdown() wait for an in-flight flush before draining.
74
+ */
75
+ private inFlight;
76
+ constructor(options: IBatchQueueOptions<T>);
77
+ /** Current number of buffered items. */
78
+ get size(): number;
79
+ /**
80
+ * Add an item to the buffer.
81
+ *
82
+ * If the queue has been shut down this is a no-op that resolves immediately.
83
+ * When the buffer reaches `maxBatch` a flush is triggered and its promise is
84
+ * returned, so a caller MAY await a size-triggered flush; otherwise resolves
85
+ * immediately.
86
+ */
87
+ enqueue(item: T): Promise<void>;
88
+ /**
89
+ * Put items back at the FRONT of the buffer ( then enforce the cap ). Owners
90
+ * use this to re-queue a batch whose `onFlush` failed, without dropping it.
91
+ */
92
+ requeueFront(items: T[]): void;
93
+ /**
94
+ * Enforce the hard `maxQueue` cap by dropping the OLDEST items. Fires
95
+ * `onOverflow(droppedItems)` with the spliced-out items when anything is dropped.
96
+ */
97
+ private enforceCap;
98
+ /**
99
+ * Flush the entire buffer in a single `onFlush` call.
100
+ *
101
+ * Re-entrancy: if a flush is already in flight, that same promise is returned
102
+ * ( no second `onFlush` ). If the buffer is empty, resolves immediately.
103
+ * Otherwise the buffer is snapshotted and cleared synchronously, `onFlush`
104
+ * runs ( optionally raced against `exportTimeoutMs` ), and the in-flight guard
105
+ * is cleared in `finally` regardless of success or failure. The returned
106
+ * promise settles with `onFlush`'s outcome so an awaiting owner can catch a
107
+ * rejection and requeue.
108
+ */
109
+ flush(): Promise<void>;
110
+ /**
111
+ * Race a flush promise against a timeout that rejects after `ms`. The timeout
112
+ * timer is cleared ( and unref()'d ) so it neither leaks nor keeps the loop alive.
113
+ */
114
+ private withTimeout;
115
+ /**
116
+ * Flush any buffered items and await completion. If a flush is already in
117
+ * flight, wait for it first, then flush any remainder that accumulated. Since
118
+ * a single `flush()` drains the ENTIRE buffer, one follow-up flush suffices.
119
+ */
120
+ forceFlush(): Promise<void>;
121
+ /**
122
+ * Stop the periodic timer and perform a best-effort final flush of buffered
123
+ * items. After shutdown, `enqueue` is a no-op that resolves.
124
+ */
125
+ shutdown(): Promise<void>;
126
+ }
127
+ //# sourceMappingURL=BatchQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BatchQueue.d.ts","sourceRoot":"","sources":["../../src/BatchQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,eAAe,EAAE,MAAM,CAAC;IACxB,+FAA+F;IAC/F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+FAA+F;IAC/F,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC;CAC1C;AAED,qBAAa,UAAU,CAAC,CAAC;IAcX,OAAO,CAAC,OAAO;IAb3B,OAAO,CAAC,MAAM,CAAW;IAEzB,OAAO,CAAC,KAAK,CAAiC;IAE9C,OAAO,CAAC,OAAO,CAAS;IAExB;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAA8B;gBAE1B,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAMlD,wCAAwC;IACxC,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;;;;;;OAOG;IACI,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAetC;;;OAGG;IACI,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI;IAKrC;;;OAGG;IACH,OAAO,CAAC,UAAU;IAQlB;;;;;;;;;;OAUG;IACI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB7B;;;OAGG;IACH,OAAO,CAAC,WAAW;IAanB;;;;OAIG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQxC;;;OAGG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAKvC"}