@bazariodev/docket 0.0.0 → 1.1.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/CHANGELOG.md +61 -0
- package/README.md +742 -169
- package/dist/browser/index.cjs +2 -2
- package/dist/browser/index.js +2 -2
- package/dist/{chunk-LRCHwVuE.js → chunk---OIebMz.js} +31 -3
- package/dist/chunk---OIebMz.js.map +1 -0
- package/dist/{chunk-CEhpwtwJ.cjs → chunk-BMmKUicm.cjs} +9 -3
- package/dist/chunk-BMmKUicm.cjs.map +1 -0
- package/dist/{chunk-B-SP8Od_.js → chunk-CJmlBW-M.js} +69 -26
- package/dist/chunk-CJmlBW-M.js.map +1 -0
- package/dist/{chunk-DYcNnkOV.js → chunk-D1NggH6k.js} +2 -2
- package/dist/{chunk-DYcNnkOV.js.map → chunk-D1NggH6k.js.map} +1 -1
- package/dist/{chunk-Bvq4tF_F.cjs → chunk-DEyTe0f4.cjs} +68 -26
- package/dist/chunk-DEyTe0f4.cjs.map +1 -0
- package/dist/{chunk-BLf-eCDO.cjs → chunk-DLnBMRjo.cjs} +3 -1
- package/dist/chunk-DLnBMRjo.cjs.map +1 -0
- package/dist/{chunk-CSS3f4_M.js → chunk-Da877R_E.js} +4 -2
- package/dist/chunk-Da877R_E.js.map +1 -0
- package/dist/{chunk-7ld72rnl.js → chunk-De6BoS1P.js} +9 -3
- package/dist/chunk-De6BoS1P.js.map +1 -0
- package/dist/{chunk-CXZYNALm.cjs → chunk-Dl2KJDqt.cjs} +31 -2
- package/dist/chunk-Dl2KJDqt.cjs.map +1 -0
- package/dist/{chunk-DqK_3eFr.cjs → chunk-DlZYLPaU.cjs} +2 -2
- package/dist/{chunk-DqK_3eFr.cjs.map → chunk-DlZYLPaU.cjs.map} +1 -1
- package/dist/client/index.cjs +167 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +40 -0
- package/dist/client/index.d.ts +40 -0
- package/dist/client/index.js +165 -0
- package/dist/client/index.js.map +1 -0
- package/dist/constants.d.cts +2 -4
- package/dist/constants.d.ts +2 -4
- package/dist/core/constants.d.cts +2 -0
- package/dist/core/constants.d.ts +2 -0
- package/dist/export/index.cjs +43 -15
- package/dist/export/index.cjs.map +1 -1
- package/dist/export/index.js +43 -15
- package/dist/export/index.js.map +1 -1
- package/dist/history/index.cjs +22 -1188
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +10 -112
- package/dist/history/index.d.ts +10 -112
- package/dist/history/index.js +22 -1188
- package/dist/history/index.js.map +1 -1
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +8 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.js +5 -5
- package/dist/indexeddb/index.cjs +18 -7
- package/dist/indexeddb/index.cjs.map +1 -1
- package/dist/indexeddb/index.d.cts +19 -4
- package/dist/indexeddb/index.d.ts +19 -4
- package/dist/indexeddb/index.js +18 -8
- package/dist/indexeddb/index.js.map +1 -1
- package/dist/redaction/index.cjs +4 -2
- package/dist/redaction/index.cjs.map +1 -1
- package/dist/redaction/index.js +4 -2
- package/dist/redaction/index.js.map +1 -1
- package/dist/sip/index.cjs +1 -1
- package/dist/sip/index.js +1 -1
- package/dist/storage/contracts.d.cts +0 -4
- package/dist/storage/contracts.d.ts +0 -4
- package/dist/upload/constants.d.cts +17 -0
- package/dist/upload/constants.d.ts +17 -0
- package/dist/upload/index.cjs +246 -0
- package/dist/upload/index.cjs.map +1 -0
- package/dist/upload/index.d.cts +51 -0
- package/dist/upload/index.d.ts +51 -0
- package/dist/upload/index.js +244 -0
- package/dist/upload/index.js.map +1 -0
- package/package.json +25 -2
- package/dist/chunk-7ld72rnl.js.map +0 -1
- package/dist/chunk-B-SP8Od_.js.map +0 -1
- package/dist/chunk-BLf-eCDO.cjs.map +0 -1
- package/dist/chunk-Bvq4tF_F.cjs.map +0 -1
- package/dist/chunk-CEhpwtwJ.cjs.map +0 -1
- package/dist/chunk-CSS3f4_M.js.map +0 -1
- package/dist/chunk-CXZYNALm.cjs.map +0 -1
- package/dist/chunk-LRCHwVuE.js.map +0 -1
- package/dist/core/errors.d.cts +0 -8
- package/dist/core/errors.d.ts +0 -8
- package/dist/history/constants.d.cts +0 -35
- package/dist/history/constants.d.ts +0 -35
- package/dist/sip/constants.d.cts +0 -5
- package/dist/sip/constants.d.ts +0 -5
package/dist/sip/index.js
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const UPLOAD_LIMITS: Readonly<{
|
|
2
|
+
MAX_INTERVAL_MS: 2147483647;
|
|
3
|
+
}>;
|
|
4
|
+
export const UPLOAD_OUTBOX_METHODS: Readonly<{
|
|
5
|
+
WRITE: "write";
|
|
6
|
+
CAPTURE: "capture";
|
|
7
|
+
FLUSH: "flush";
|
|
8
|
+
NEXT_BATCH: "nextBatch";
|
|
9
|
+
ACKNOWLEDGE: "acknowledge";
|
|
10
|
+
GET_STATUS: "getStatus";
|
|
11
|
+
}>;
|
|
12
|
+
export const UPLOAD_STORAGE_MODES: Readonly<{
|
|
13
|
+
MEMORY: "memory";
|
|
14
|
+
PERSISTENT: "persistent";
|
|
15
|
+
FAILED: "failed";
|
|
16
|
+
STOPPED: "stopped";
|
|
17
|
+
}>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const UPLOAD_LIMITS: Readonly<{
|
|
2
|
+
MAX_INTERVAL_MS: 2147483647;
|
|
3
|
+
}>;
|
|
4
|
+
export const UPLOAD_OUTBOX_METHODS: Readonly<{
|
|
5
|
+
WRITE: "write";
|
|
6
|
+
CAPTURE: "capture";
|
|
7
|
+
FLUSH: "flush";
|
|
8
|
+
NEXT_BATCH: "nextBatch";
|
|
9
|
+
ACKNOWLEDGE: "acknowledge";
|
|
10
|
+
GET_STATUS: "getStatus";
|
|
11
|
+
}>;
|
|
12
|
+
export const UPLOAD_STORAGE_MODES: Readonly<{
|
|
13
|
+
MEMORY: "memory";
|
|
14
|
+
PERSISTENT: "persistent";
|
|
15
|
+
FAILED: "failed";
|
|
16
|
+
STOPPED: "stopped";
|
|
17
|
+
}>;
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var common = require('../chunk-Dl2KJDqt.cjs');
|
|
4
|
+
require('../chunk-DLnBMRjo.cjs');
|
|
5
|
+
|
|
6
|
+
const UPLOAD_LIMITS = Object.freeze({ MAX_INTERVAL_MS: 2_147_483_647 });
|
|
7
|
+
|
|
8
|
+
const UPLOAD_OUTBOX_METHODS = Object.freeze({
|
|
9
|
+
WRITE: 'write',
|
|
10
|
+
CAPTURE: 'capture',
|
|
11
|
+
FLUSH: 'flush',
|
|
12
|
+
NEXT_BATCH: 'nextBatch',
|
|
13
|
+
ACKNOWLEDGE: 'acknowledge',
|
|
14
|
+
GET_STATUS: 'getStatus',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const UPLOAD_STORAGE_MODES = Object.freeze({
|
|
18
|
+
MEMORY: 'memory',
|
|
19
|
+
PERSISTENT: 'persistent',
|
|
20
|
+
FAILED: 'failed',
|
|
21
|
+
STOPPED: 'stopped',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
class UploadSink {
|
|
25
|
+
#outbox;
|
|
26
|
+
#options;
|
|
27
|
+
#scheduler;
|
|
28
|
+
#timer;
|
|
29
|
+
#operation;
|
|
30
|
+
#acceptedToken;
|
|
31
|
+
#paused = false;
|
|
32
|
+
#storageFailureReported = false;
|
|
33
|
+
#droppedRecords = 0;
|
|
34
|
+
#stopped = false;
|
|
35
|
+
#stopPromise;
|
|
36
|
+
|
|
37
|
+
constructor(options, outbox, scheduler) {
|
|
38
|
+
this.#options = options;
|
|
39
|
+
this.#outbox = outbox;
|
|
40
|
+
this.#scheduler = scheduler;
|
|
41
|
+
this.#schedule();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
write(record) {
|
|
45
|
+
if (this.#stopped) return;
|
|
46
|
+
const status = this.#readStatus();
|
|
47
|
+
if (this.#stopped) return;
|
|
48
|
+
if (status.mode === UPLOAD_STORAGE_MODES.FAILED) {
|
|
49
|
+
this.#drop(status.error);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
this.#outbox.write(record);
|
|
54
|
+
} catch (failure) {
|
|
55
|
+
if (this.#readStatus().mode !== UPLOAD_STORAGE_MODES.FAILED)
|
|
56
|
+
throw failure;
|
|
57
|
+
this.#drop(failure);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
this.#schedule();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#readStatus() {
|
|
64
|
+
const status = this.#outbox.getStatus();
|
|
65
|
+
if (status.mode !== UPLOAD_STORAGE_MODES.FAILED)
|
|
66
|
+
this.#storageFailureReported = false;
|
|
67
|
+
return status;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#drop(failure) {
|
|
71
|
+
this.#droppedRecords++;
|
|
72
|
+
if (this.#storageFailureReported) return;
|
|
73
|
+
this.#storageFailureReported = true;
|
|
74
|
+
common.report(this.#options.onError, failure);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#cancelTimer() {
|
|
78
|
+
if (!this.#timer) return;
|
|
79
|
+
this.#scheduler.clearTimeout(this.#timer.handle);
|
|
80
|
+
this.#timer = undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#schedule() {
|
|
84
|
+
if (this.#stopped || this.#paused || this.#timer || this.#operation) return;
|
|
85
|
+
const status = this.#readStatus();
|
|
86
|
+
if (this.#stopped || this.#paused || this.#timer || this.#operation) return;
|
|
87
|
+
if (
|
|
88
|
+
status.mode === UPLOAD_STORAGE_MODES.FAILED ||
|
|
89
|
+
status.mode === UPLOAD_STORAGE_MODES.STOPPED
|
|
90
|
+
)
|
|
91
|
+
return;
|
|
92
|
+
if (!status.pendingRecords && !status.batchRecords) return;
|
|
93
|
+
this.#timer = {
|
|
94
|
+
handle: this.#scheduler.setTimeout(() => {
|
|
95
|
+
this.#timer = undefined;
|
|
96
|
+
void this.flush().catch(() => {});
|
|
97
|
+
}, this.#options.intervalMs),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
flush() {
|
|
102
|
+
if (this.#stopped) return Promise.resolve();
|
|
103
|
+
this.#cancelTimer();
|
|
104
|
+
const current = this.#operation;
|
|
105
|
+
if (current) {
|
|
106
|
+
try {
|
|
107
|
+
current.boundary = this.#outbox.capture();
|
|
108
|
+
} catch (failure) {
|
|
109
|
+
return Promise.reject(failure);
|
|
110
|
+
}
|
|
111
|
+
return current.promise;
|
|
112
|
+
}
|
|
113
|
+
this.#paused = false;
|
|
114
|
+
let resolve;
|
|
115
|
+
let reject;
|
|
116
|
+
const promise = new Promise((accept, fail) => {
|
|
117
|
+
resolve = accept;
|
|
118
|
+
reject = fail;
|
|
119
|
+
});
|
|
120
|
+
const operation = {
|
|
121
|
+
promise,
|
|
122
|
+
resolve,
|
|
123
|
+
reject,
|
|
124
|
+
boundary: undefined,
|
|
125
|
+
controller: undefined,
|
|
126
|
+
};
|
|
127
|
+
this.#operation = operation;
|
|
128
|
+
try {
|
|
129
|
+
operation.boundary = this.#outbox.capture();
|
|
130
|
+
} catch (failure) {
|
|
131
|
+
this.#fail(operation, failure);
|
|
132
|
+
return promise;
|
|
133
|
+
}
|
|
134
|
+
void this.#drain(operation);
|
|
135
|
+
return promise;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async #drain(operation) {
|
|
139
|
+
try {
|
|
140
|
+
if (this.#stopped || this.#operation !== operation) return;
|
|
141
|
+
await this.#outbox.flush();
|
|
142
|
+
this.#readStatus();
|
|
143
|
+
while (!this.#stopped && this.#operation === operation) {
|
|
144
|
+
const boundary = operation.boundary;
|
|
145
|
+
const batch = await this.#outbox.nextBatch(
|
|
146
|
+
this.#options.maxBatchRecords,
|
|
147
|
+
boundary,
|
|
148
|
+
);
|
|
149
|
+
if (this.#stopped || this.#operation !== operation) return;
|
|
150
|
+
if (!batch) {
|
|
151
|
+
if (boundary !== operation.boundary) continue;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
if (this.#acceptedToken !== batch.token) {
|
|
155
|
+
operation.controller = new AbortController();
|
|
156
|
+
await this.#options.send(
|
|
157
|
+
batch.records,
|
|
158
|
+
operation.controller.signal,
|
|
159
|
+
batch.token,
|
|
160
|
+
);
|
|
161
|
+
if (this.#stopped || this.#operation !== operation) return;
|
|
162
|
+
this.#acceptedToken = batch.token;
|
|
163
|
+
}
|
|
164
|
+
await this.#outbox.acknowledge(batch.token);
|
|
165
|
+
this.#acceptedToken = undefined;
|
|
166
|
+
}
|
|
167
|
+
if (this.#stopped || this.#operation !== operation) return;
|
|
168
|
+
this.#operation = undefined;
|
|
169
|
+
this.#schedule();
|
|
170
|
+
operation.resolve();
|
|
171
|
+
} catch (failure) {
|
|
172
|
+
this.#fail(operation, failure);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
#fail(operation, failure) {
|
|
177
|
+
operation.reject(failure);
|
|
178
|
+
if (this.#stopped) return;
|
|
179
|
+
this.#operation ??= operation;
|
|
180
|
+
if (this.#operation === operation) {
|
|
181
|
+
this.#paused = true;
|
|
182
|
+
this.#cancelTimer();
|
|
183
|
+
}
|
|
184
|
+
common.report(this.#options.onError, failure);
|
|
185
|
+
if (this.#operation === operation) this.#operation = undefined;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
stop() {
|
|
189
|
+
if (this.#stopPromise) return this.#stopPromise;
|
|
190
|
+
this.#stopped = true;
|
|
191
|
+
this.#cancelTimer();
|
|
192
|
+
const operation = this.#operation;
|
|
193
|
+
this.#operation = undefined;
|
|
194
|
+
this.#stopPromise = Promise.resolve();
|
|
195
|
+
if (operation) {
|
|
196
|
+
const failure = new DOMException('Upload stopped', 'AbortError');
|
|
197
|
+
operation.reject(failure);
|
|
198
|
+
operation.controller?.abort(failure);
|
|
199
|
+
}
|
|
200
|
+
return this.#stopPromise;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
getStatus() {
|
|
204
|
+
const { mode, pendingRecords, batchRecords, droppedRecords, error } =
|
|
205
|
+
this.#readStatus();
|
|
206
|
+
return Object.freeze({
|
|
207
|
+
mode,
|
|
208
|
+
pendingRecords,
|
|
209
|
+
batchRecords,
|
|
210
|
+
droppedRecords: droppedRecords + this.#droppedRecords,
|
|
211
|
+
...(error === undefined ? {} : { error }),
|
|
212
|
+
paused: this.#paused,
|
|
213
|
+
stopped: this.#stopped,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function createUploadSink(options, outbox) {
|
|
219
|
+
common.positive(options?.maxBatchRecords, 'maxBatchRecords');
|
|
220
|
+
common.positive(options.intervalMs, 'intervalMs');
|
|
221
|
+
const scheduler =
|
|
222
|
+
options.scheduler === undefined ? common.scheduler : options.scheduler;
|
|
223
|
+
if (
|
|
224
|
+
options.intervalMs > UPLOAD_LIMITS.MAX_INTERVAL_MS ||
|
|
225
|
+
typeof options.send !== 'function' ||
|
|
226
|
+
(options.onError !== undefined && typeof options.onError !== 'function') ||
|
|
227
|
+
!scheduler ||
|
|
228
|
+
typeof scheduler.setTimeout !== 'function' ||
|
|
229
|
+
typeof scheduler.clearTimeout !== 'function' ||
|
|
230
|
+
!outbox ||
|
|
231
|
+
Object.values(UPLOAD_OUTBOX_METHODS).some(
|
|
232
|
+
(method) => typeof outbox[method] !== 'function',
|
|
233
|
+
)
|
|
234
|
+
)
|
|
235
|
+
throw new TypeError('Invalid upload options');
|
|
236
|
+
const sink = new UploadSink(options, outbox, scheduler);
|
|
237
|
+
return Object.freeze({
|
|
238
|
+
write: (record) => sink.write(record),
|
|
239
|
+
flush: () => sink.flush(),
|
|
240
|
+
stop: () => sink.stop(),
|
|
241
|
+
getStatus: () => sink.getStatus(),
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
exports.createUploadSink = createUploadSink;
|
|
246
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/upload/constants.js","../../src/upload/index.js"],"sourcesContent":["export const UPLOAD_LIMITS = Object.freeze({ MAX_INTERVAL_MS: 2_147_483_647 });\n\nexport const UPLOAD_OUTBOX_METHODS = Object.freeze({\n WRITE: 'write',\n CAPTURE: 'capture',\n FLUSH: 'flush',\n NEXT_BATCH: 'nextBatch',\n ACKNOWLEDGE: 'acknowledge',\n GET_STATUS: 'getStatus',\n});\n\nexport const UPLOAD_STORAGE_MODES = Object.freeze({\n MEMORY: 'memory',\n PERSISTENT: 'persistent',\n FAILED: 'failed',\n STOPPED: 'stopped',\n});\n","import {\n scheduler as hostScheduler,\n positive,\n report,\n} from '../core/common.js';\nimport {\n UPLOAD_LIMITS,\n UPLOAD_OUTBOX_METHODS,\n UPLOAD_STORAGE_MODES,\n} from './constants.js';\n\nclass UploadSink {\n #outbox;\n #options;\n #scheduler;\n #timer;\n #operation;\n #acceptedToken;\n #paused = false;\n #storageFailureReported = false;\n #droppedRecords = 0;\n #stopped = false;\n #stopPromise;\n\n constructor(options, outbox, scheduler) {\n this.#options = options;\n this.#outbox = outbox;\n this.#scheduler = scheduler;\n this.#schedule();\n }\n\n write(record) {\n if (this.#stopped) return;\n const status = this.#readStatus();\n if (this.#stopped) return;\n if (status.mode === UPLOAD_STORAGE_MODES.FAILED) {\n this.#drop(status.error);\n return;\n }\n try {\n this.#outbox.write(record);\n } catch (failure) {\n if (this.#readStatus().mode !== UPLOAD_STORAGE_MODES.FAILED)\n throw failure;\n this.#drop(failure);\n return;\n }\n this.#schedule();\n }\n\n #readStatus() {\n const status = this.#outbox.getStatus();\n if (status.mode !== UPLOAD_STORAGE_MODES.FAILED)\n this.#storageFailureReported = false;\n return status;\n }\n\n #drop(failure) {\n this.#droppedRecords++;\n if (this.#storageFailureReported) return;\n this.#storageFailureReported = true;\n report(this.#options.onError, failure);\n }\n\n #cancelTimer() {\n if (!this.#timer) return;\n this.#scheduler.clearTimeout(this.#timer.handle);\n this.#timer = undefined;\n }\n\n #schedule() {\n if (this.#stopped || this.#paused || this.#timer || this.#operation) return;\n const status = this.#readStatus();\n if (this.#stopped || this.#paused || this.#timer || this.#operation) return;\n if (\n status.mode === UPLOAD_STORAGE_MODES.FAILED ||\n status.mode === UPLOAD_STORAGE_MODES.STOPPED\n )\n return;\n if (!status.pendingRecords && !status.batchRecords) return;\n this.#timer = {\n handle: this.#scheduler.setTimeout(() => {\n this.#timer = undefined;\n void this.flush().catch(() => {});\n }, this.#options.intervalMs),\n };\n }\n\n flush() {\n if (this.#stopped) return Promise.resolve();\n this.#cancelTimer();\n const current = this.#operation;\n if (current) {\n try {\n current.boundary = this.#outbox.capture();\n } catch (failure) {\n return Promise.reject(failure);\n }\n return current.promise;\n }\n this.#paused = false;\n let resolve;\n let reject;\n const promise = new Promise((accept, fail) => {\n resolve = accept;\n reject = fail;\n });\n const operation = {\n promise,\n resolve,\n reject,\n boundary: undefined,\n controller: undefined,\n };\n this.#operation = operation;\n try {\n operation.boundary = this.#outbox.capture();\n } catch (failure) {\n this.#fail(operation, failure);\n return promise;\n }\n void this.#drain(operation);\n return promise;\n }\n\n async #drain(operation) {\n try {\n if (this.#stopped || this.#operation !== operation) return;\n await this.#outbox.flush();\n this.#readStatus();\n while (!this.#stopped && this.#operation === operation) {\n const boundary = operation.boundary;\n const batch = await this.#outbox.nextBatch(\n this.#options.maxBatchRecords,\n boundary,\n );\n if (this.#stopped || this.#operation !== operation) return;\n if (!batch) {\n if (boundary !== operation.boundary) continue;\n break;\n }\n if (this.#acceptedToken !== batch.token) {\n operation.controller = new AbortController();\n await this.#options.send(\n batch.records,\n operation.controller.signal,\n batch.token,\n );\n if (this.#stopped || this.#operation !== operation) return;\n this.#acceptedToken = batch.token;\n }\n await this.#outbox.acknowledge(batch.token);\n this.#acceptedToken = undefined;\n }\n if (this.#stopped || this.#operation !== operation) return;\n this.#operation = undefined;\n this.#schedule();\n operation.resolve();\n } catch (failure) {\n this.#fail(operation, failure);\n }\n }\n\n #fail(operation, failure) {\n operation.reject(failure);\n if (this.#stopped) return;\n this.#operation ??= operation;\n if (this.#operation === operation) {\n this.#paused = true;\n this.#cancelTimer();\n }\n report(this.#options.onError, failure);\n if (this.#operation === operation) this.#operation = undefined;\n }\n\n stop() {\n if (this.#stopPromise) return this.#stopPromise;\n this.#stopped = true;\n this.#cancelTimer();\n const operation = this.#operation;\n this.#operation = undefined;\n this.#stopPromise = Promise.resolve();\n if (operation) {\n const failure = new DOMException('Upload stopped', 'AbortError');\n operation.reject(failure);\n operation.controller?.abort(failure);\n }\n return this.#stopPromise;\n }\n\n getStatus() {\n const { mode, pendingRecords, batchRecords, droppedRecords, error } =\n this.#readStatus();\n return Object.freeze({\n mode,\n pendingRecords,\n batchRecords,\n droppedRecords: droppedRecords + this.#droppedRecords,\n ...(error === undefined ? {} : { error }),\n paused: this.#paused,\n stopped: this.#stopped,\n });\n }\n}\n\nexport function createUploadSink(options, outbox) {\n positive(options?.maxBatchRecords, 'maxBatchRecords');\n positive(options.intervalMs, 'intervalMs');\n const scheduler =\n options.scheduler === undefined ? hostScheduler : options.scheduler;\n if (\n options.intervalMs > UPLOAD_LIMITS.MAX_INTERVAL_MS ||\n typeof options.send !== 'function' ||\n (options.onError !== undefined && typeof options.onError !== 'function') ||\n !scheduler ||\n typeof scheduler.setTimeout !== 'function' ||\n typeof scheduler.clearTimeout !== 'function' ||\n !outbox ||\n Object.values(UPLOAD_OUTBOX_METHODS).some(\n (method) => typeof outbox[method] !== 'function',\n )\n )\n throw new TypeError('Invalid upload options');\n const sink = new UploadSink(options, outbox, scheduler);\n return Object.freeze({\n write: (record) => sink.write(record),\n flush: () => sink.flush(),\n stop: () => sink.stop(),\n getStatus: () => sink.getStatus(),\n });\n}\n"],"names":["report","positive","hostScheduler"],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { LoggingScheduler, LogRecord } from "../index.cjs";
|
|
2
|
+
import type { UPLOAD_STORAGE_MODES } from "./constants.cjs";
|
|
3
|
+
|
|
4
|
+
type ValueOf<Values> = Values[keyof Values];
|
|
5
|
+
|
|
6
|
+
export type UploadBatch = Readonly<{
|
|
7
|
+
token: string;
|
|
8
|
+
records: readonly LogRecord[];
|
|
9
|
+
}>;
|
|
10
|
+
export type UploadStorageMode =
|
|
11
|
+
| ValueOf<typeof UPLOAD_STORAGE_MODES>
|
|
12
|
+
| (string & {});
|
|
13
|
+
export type UploadOutboxStatus = Readonly<{
|
|
14
|
+
mode: UploadStorageMode;
|
|
15
|
+
error?: unknown;
|
|
16
|
+
pendingRecords: number;
|
|
17
|
+
batchRecords: number;
|
|
18
|
+
droppedRecords: number;
|
|
19
|
+
}>;
|
|
20
|
+
export type UploadOutbox = Readonly<{
|
|
21
|
+
write(record: LogRecord): void;
|
|
22
|
+
capture(): string;
|
|
23
|
+
flush(): Promise<void>;
|
|
24
|
+
nextBatch(limit: number, boundary: string): Promise<UploadBatch | null>;
|
|
25
|
+
acknowledge(token: string): Promise<void>;
|
|
26
|
+
getStatus(): UploadOutboxStatus;
|
|
27
|
+
}>;
|
|
28
|
+
|
|
29
|
+
export type UploadSinkOptions = Readonly<{
|
|
30
|
+
maxBatchRecords: number;
|
|
31
|
+
intervalMs: number;
|
|
32
|
+
send: (
|
|
33
|
+
records: readonly LogRecord[],
|
|
34
|
+
signal: AbortSignal,
|
|
35
|
+
token: string,
|
|
36
|
+
) => Promise<void>;
|
|
37
|
+
onError?: (error: unknown) => void;
|
|
38
|
+
scheduler?: LoggingScheduler;
|
|
39
|
+
}>;
|
|
40
|
+
export type UploadSinkStatus = UploadOutboxStatus &
|
|
41
|
+
Readonly<{ paused: boolean; stopped: boolean }>;
|
|
42
|
+
export type UploadSink = Readonly<{
|
|
43
|
+
write(record: LogRecord): void;
|
|
44
|
+
flush(): Promise<void>;
|
|
45
|
+
stop(): Promise<void>;
|
|
46
|
+
getStatus(): UploadSinkStatus;
|
|
47
|
+
}>;
|
|
48
|
+
export declare function createUploadSink(
|
|
49
|
+
options: UploadSinkOptions,
|
|
50
|
+
outbox: UploadOutbox,
|
|
51
|
+
): UploadSink;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { LoggingScheduler, LogRecord } from '../index.js';
|
|
2
|
+
import type { UPLOAD_STORAGE_MODES } from './constants.js';
|
|
3
|
+
|
|
4
|
+
type ValueOf<Values> = Values[keyof Values];
|
|
5
|
+
|
|
6
|
+
export type UploadBatch = Readonly<{
|
|
7
|
+
token: string;
|
|
8
|
+
records: readonly LogRecord[];
|
|
9
|
+
}>;
|
|
10
|
+
export type UploadStorageMode =
|
|
11
|
+
| ValueOf<typeof UPLOAD_STORAGE_MODES>
|
|
12
|
+
| (string & {});
|
|
13
|
+
export type UploadOutboxStatus = Readonly<{
|
|
14
|
+
mode: UploadStorageMode;
|
|
15
|
+
error?: unknown;
|
|
16
|
+
pendingRecords: number;
|
|
17
|
+
batchRecords: number;
|
|
18
|
+
droppedRecords: number;
|
|
19
|
+
}>;
|
|
20
|
+
export type UploadOutbox = Readonly<{
|
|
21
|
+
write(record: LogRecord): void;
|
|
22
|
+
capture(): string;
|
|
23
|
+
flush(): Promise<void>;
|
|
24
|
+
nextBatch(limit: number, boundary: string): Promise<UploadBatch | null>;
|
|
25
|
+
acknowledge(token: string): Promise<void>;
|
|
26
|
+
getStatus(): UploadOutboxStatus;
|
|
27
|
+
}>;
|
|
28
|
+
|
|
29
|
+
export type UploadSinkOptions = Readonly<{
|
|
30
|
+
maxBatchRecords: number;
|
|
31
|
+
intervalMs: number;
|
|
32
|
+
send: (
|
|
33
|
+
records: readonly LogRecord[],
|
|
34
|
+
signal: AbortSignal,
|
|
35
|
+
token: string,
|
|
36
|
+
) => Promise<void>;
|
|
37
|
+
onError?: (error: unknown) => void;
|
|
38
|
+
scheduler?: LoggingScheduler;
|
|
39
|
+
}>;
|
|
40
|
+
export type UploadSinkStatus = UploadOutboxStatus &
|
|
41
|
+
Readonly<{ paused: boolean; stopped: boolean }>;
|
|
42
|
+
export type UploadSink = Readonly<{
|
|
43
|
+
write(record: LogRecord): void;
|
|
44
|
+
flush(): Promise<void>;
|
|
45
|
+
stop(): Promise<void>;
|
|
46
|
+
getStatus(): UploadSinkStatus;
|
|
47
|
+
}>;
|
|
48
|
+
export declare function createUploadSink(
|
|
49
|
+
options: UploadSinkOptions,
|
|
50
|
+
outbox: UploadOutbox,
|
|
51
|
+
): UploadSink;
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { p as positive, s as scheduler, b as report } from '../chunk---OIebMz.js';
|
|
2
|
+
import '../chunk-Da877R_E.js';
|
|
3
|
+
|
|
4
|
+
const UPLOAD_LIMITS = Object.freeze({ MAX_INTERVAL_MS: 2_147_483_647 });
|
|
5
|
+
|
|
6
|
+
const UPLOAD_OUTBOX_METHODS = Object.freeze({
|
|
7
|
+
WRITE: 'write',
|
|
8
|
+
CAPTURE: 'capture',
|
|
9
|
+
FLUSH: 'flush',
|
|
10
|
+
NEXT_BATCH: 'nextBatch',
|
|
11
|
+
ACKNOWLEDGE: 'acknowledge',
|
|
12
|
+
GET_STATUS: 'getStatus',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const UPLOAD_STORAGE_MODES = Object.freeze({
|
|
16
|
+
MEMORY: 'memory',
|
|
17
|
+
PERSISTENT: 'persistent',
|
|
18
|
+
FAILED: 'failed',
|
|
19
|
+
STOPPED: 'stopped',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
class UploadSink {
|
|
23
|
+
#outbox;
|
|
24
|
+
#options;
|
|
25
|
+
#scheduler;
|
|
26
|
+
#timer;
|
|
27
|
+
#operation;
|
|
28
|
+
#acceptedToken;
|
|
29
|
+
#paused = false;
|
|
30
|
+
#storageFailureReported = false;
|
|
31
|
+
#droppedRecords = 0;
|
|
32
|
+
#stopped = false;
|
|
33
|
+
#stopPromise;
|
|
34
|
+
|
|
35
|
+
constructor(options, outbox, scheduler) {
|
|
36
|
+
this.#options = options;
|
|
37
|
+
this.#outbox = outbox;
|
|
38
|
+
this.#scheduler = scheduler;
|
|
39
|
+
this.#schedule();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
write(record) {
|
|
43
|
+
if (this.#stopped) return;
|
|
44
|
+
const status = this.#readStatus();
|
|
45
|
+
if (this.#stopped) return;
|
|
46
|
+
if (status.mode === UPLOAD_STORAGE_MODES.FAILED) {
|
|
47
|
+
this.#drop(status.error);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
this.#outbox.write(record);
|
|
52
|
+
} catch (failure) {
|
|
53
|
+
if (this.#readStatus().mode !== UPLOAD_STORAGE_MODES.FAILED)
|
|
54
|
+
throw failure;
|
|
55
|
+
this.#drop(failure);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this.#schedule();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#readStatus() {
|
|
62
|
+
const status = this.#outbox.getStatus();
|
|
63
|
+
if (status.mode !== UPLOAD_STORAGE_MODES.FAILED)
|
|
64
|
+
this.#storageFailureReported = false;
|
|
65
|
+
return status;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#drop(failure) {
|
|
69
|
+
this.#droppedRecords++;
|
|
70
|
+
if (this.#storageFailureReported) return;
|
|
71
|
+
this.#storageFailureReported = true;
|
|
72
|
+
report(this.#options.onError, failure);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
#cancelTimer() {
|
|
76
|
+
if (!this.#timer) return;
|
|
77
|
+
this.#scheduler.clearTimeout(this.#timer.handle);
|
|
78
|
+
this.#timer = undefined;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#schedule() {
|
|
82
|
+
if (this.#stopped || this.#paused || this.#timer || this.#operation) return;
|
|
83
|
+
const status = this.#readStatus();
|
|
84
|
+
if (this.#stopped || this.#paused || this.#timer || this.#operation) return;
|
|
85
|
+
if (
|
|
86
|
+
status.mode === UPLOAD_STORAGE_MODES.FAILED ||
|
|
87
|
+
status.mode === UPLOAD_STORAGE_MODES.STOPPED
|
|
88
|
+
)
|
|
89
|
+
return;
|
|
90
|
+
if (!status.pendingRecords && !status.batchRecords) return;
|
|
91
|
+
this.#timer = {
|
|
92
|
+
handle: this.#scheduler.setTimeout(() => {
|
|
93
|
+
this.#timer = undefined;
|
|
94
|
+
void this.flush().catch(() => {});
|
|
95
|
+
}, this.#options.intervalMs),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
flush() {
|
|
100
|
+
if (this.#stopped) return Promise.resolve();
|
|
101
|
+
this.#cancelTimer();
|
|
102
|
+
const current = this.#operation;
|
|
103
|
+
if (current) {
|
|
104
|
+
try {
|
|
105
|
+
current.boundary = this.#outbox.capture();
|
|
106
|
+
} catch (failure) {
|
|
107
|
+
return Promise.reject(failure);
|
|
108
|
+
}
|
|
109
|
+
return current.promise;
|
|
110
|
+
}
|
|
111
|
+
this.#paused = false;
|
|
112
|
+
let resolve;
|
|
113
|
+
let reject;
|
|
114
|
+
const promise = new Promise((accept, fail) => {
|
|
115
|
+
resolve = accept;
|
|
116
|
+
reject = fail;
|
|
117
|
+
});
|
|
118
|
+
const operation = {
|
|
119
|
+
promise,
|
|
120
|
+
resolve,
|
|
121
|
+
reject,
|
|
122
|
+
boundary: undefined,
|
|
123
|
+
controller: undefined,
|
|
124
|
+
};
|
|
125
|
+
this.#operation = operation;
|
|
126
|
+
try {
|
|
127
|
+
operation.boundary = this.#outbox.capture();
|
|
128
|
+
} catch (failure) {
|
|
129
|
+
this.#fail(operation, failure);
|
|
130
|
+
return promise;
|
|
131
|
+
}
|
|
132
|
+
void this.#drain(operation);
|
|
133
|
+
return promise;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async #drain(operation) {
|
|
137
|
+
try {
|
|
138
|
+
if (this.#stopped || this.#operation !== operation) return;
|
|
139
|
+
await this.#outbox.flush();
|
|
140
|
+
this.#readStatus();
|
|
141
|
+
while (!this.#stopped && this.#operation === operation) {
|
|
142
|
+
const boundary = operation.boundary;
|
|
143
|
+
const batch = await this.#outbox.nextBatch(
|
|
144
|
+
this.#options.maxBatchRecords,
|
|
145
|
+
boundary,
|
|
146
|
+
);
|
|
147
|
+
if (this.#stopped || this.#operation !== operation) return;
|
|
148
|
+
if (!batch) {
|
|
149
|
+
if (boundary !== operation.boundary) continue;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
if (this.#acceptedToken !== batch.token) {
|
|
153
|
+
operation.controller = new AbortController();
|
|
154
|
+
await this.#options.send(
|
|
155
|
+
batch.records,
|
|
156
|
+
operation.controller.signal,
|
|
157
|
+
batch.token,
|
|
158
|
+
);
|
|
159
|
+
if (this.#stopped || this.#operation !== operation) return;
|
|
160
|
+
this.#acceptedToken = batch.token;
|
|
161
|
+
}
|
|
162
|
+
await this.#outbox.acknowledge(batch.token);
|
|
163
|
+
this.#acceptedToken = undefined;
|
|
164
|
+
}
|
|
165
|
+
if (this.#stopped || this.#operation !== operation) return;
|
|
166
|
+
this.#operation = undefined;
|
|
167
|
+
this.#schedule();
|
|
168
|
+
operation.resolve();
|
|
169
|
+
} catch (failure) {
|
|
170
|
+
this.#fail(operation, failure);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
#fail(operation, failure) {
|
|
175
|
+
operation.reject(failure);
|
|
176
|
+
if (this.#stopped) return;
|
|
177
|
+
this.#operation ??= operation;
|
|
178
|
+
if (this.#operation === operation) {
|
|
179
|
+
this.#paused = true;
|
|
180
|
+
this.#cancelTimer();
|
|
181
|
+
}
|
|
182
|
+
report(this.#options.onError, failure);
|
|
183
|
+
if (this.#operation === operation) this.#operation = undefined;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
stop() {
|
|
187
|
+
if (this.#stopPromise) return this.#stopPromise;
|
|
188
|
+
this.#stopped = true;
|
|
189
|
+
this.#cancelTimer();
|
|
190
|
+
const operation = this.#operation;
|
|
191
|
+
this.#operation = undefined;
|
|
192
|
+
this.#stopPromise = Promise.resolve();
|
|
193
|
+
if (operation) {
|
|
194
|
+
const failure = new DOMException('Upload stopped', 'AbortError');
|
|
195
|
+
operation.reject(failure);
|
|
196
|
+
operation.controller?.abort(failure);
|
|
197
|
+
}
|
|
198
|
+
return this.#stopPromise;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
getStatus() {
|
|
202
|
+
const { mode, pendingRecords, batchRecords, droppedRecords, error } =
|
|
203
|
+
this.#readStatus();
|
|
204
|
+
return Object.freeze({
|
|
205
|
+
mode,
|
|
206
|
+
pendingRecords,
|
|
207
|
+
batchRecords,
|
|
208
|
+
droppedRecords: droppedRecords + this.#droppedRecords,
|
|
209
|
+
...(error === undefined ? {} : { error }),
|
|
210
|
+
paused: this.#paused,
|
|
211
|
+
stopped: this.#stopped,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function createUploadSink(options, outbox) {
|
|
217
|
+
positive(options?.maxBatchRecords, 'maxBatchRecords');
|
|
218
|
+
positive(options.intervalMs, 'intervalMs');
|
|
219
|
+
const scheduler$1 =
|
|
220
|
+
options.scheduler === undefined ? scheduler : options.scheduler;
|
|
221
|
+
if (
|
|
222
|
+
options.intervalMs > UPLOAD_LIMITS.MAX_INTERVAL_MS ||
|
|
223
|
+
typeof options.send !== 'function' ||
|
|
224
|
+
(options.onError !== undefined && typeof options.onError !== 'function') ||
|
|
225
|
+
!scheduler$1 ||
|
|
226
|
+
typeof scheduler$1.setTimeout !== 'function' ||
|
|
227
|
+
typeof scheduler$1.clearTimeout !== 'function' ||
|
|
228
|
+
!outbox ||
|
|
229
|
+
Object.values(UPLOAD_OUTBOX_METHODS).some(
|
|
230
|
+
(method) => typeof outbox[method] !== 'function',
|
|
231
|
+
)
|
|
232
|
+
)
|
|
233
|
+
throw new TypeError('Invalid upload options');
|
|
234
|
+
const sink = new UploadSink(options, outbox, scheduler$1);
|
|
235
|
+
return Object.freeze({
|
|
236
|
+
write: (record) => sink.write(record),
|
|
237
|
+
flush: () => sink.flush(),
|
|
238
|
+
stop: () => sink.stop(),
|
|
239
|
+
getStatus: () => sink.getStatus(),
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export { createUploadSink };
|
|
244
|
+
//# sourceMappingURL=index.js.map
|