@lossless.org/objectstorage 11.0.0 → 11.2.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.
Files changed (51) hide show
  1. package/.smartconfig.json +19 -1
  2. package/dist_rust/ruststorage_linux_amd64 +0 -0
  3. package/dist_rust/ruststorage_linux_amd64.tsrust-build.json +4 -4
  4. package/dist_rust/ruststorage_linux_amd64_musl +0 -0
  5. package/dist_rust/ruststorage_linux_amd64_musl.tsrust-build.json +4 -4
  6. package/dist_rust/ruststorage_linux_arm64 +0 -0
  7. package/dist_rust/ruststorage_linux_arm64.tsrust-build.json +4 -4
  8. package/dist_rust/ruststorage_linux_arm64_musl +0 -0
  9. package/dist_rust/ruststorage_linux_arm64_musl.tsrust-build.json +4 -4
  10. package/dist_rust/ruststorage_macos_amd64 +0 -0
  11. package/dist_rust/ruststorage_macos_amd64.tsrust-build.json +4 -4
  12. package/dist_rust/ruststorage_macos_arm64 +0 -0
  13. package/dist_rust/ruststorage_macos_arm64.tsrust-build.json +4 -4
  14. package/dist_ts/00_commitinfo_data.js +1 -1
  15. package/dist_ts/classes.dashboard.d.ts +49 -0
  16. package/dist_ts/classes.dashboard.js +234 -0
  17. package/dist_ts/dashboard.bundled.d.ts +4 -0
  18. package/dist_ts/dashboard.bundled.js +20 -0
  19. package/dist_ts/dashboard.interfaces.d.ts +132 -0
  20. package/dist_ts/dashboard.interfaces.js +2 -0
  21. package/dist_ts/dashboard.plugins.d.ts +5 -0
  22. package/dist_ts/dashboard.plugins.js +10 -0
  23. package/dist_ts/index.d.ts +116 -1
  24. package/dist_ts/index.js +90 -2
  25. package/package.json +11 -7
  26. package/readme.md +400 -22
  27. package/third-party-notices.md +20 -4
  28. package/third_party_licenses/borsh-1.8.1-license.txt +23 -0
  29. package/third_party_licenses/borsh-derive-1.8.1-apache-2.0.txt +201 -0
  30. package/third_party_licenses/cargo-dependencies.html +420 -0
  31. package/third_party_licenses/dyn-clone-1.0.20-license.txt +23 -0
  32. package/third_party_licenses/equivalent-1.0.3-license.txt +25 -0
  33. package/third_party_licenses/hashbrown-0.17.1-license.txt +25 -0
  34. package/third_party_licenses/indexmap-2.14.2-license.txt +25 -0
  35. package/third_party_licenses/inventory.json +310 -8
  36. package/third_party_licenses/proc-macro-crate-3.5.0-license.txt +23 -0
  37. package/third_party_licenses/ref-cast-1.0.27-license.txt +23 -0
  38. package/third_party_licenses/ref-cast-impl-1.0.27-license.txt +23 -0
  39. package/third_party_licenses/schemars-1.2.3-license.txt +21 -0
  40. package/third_party_licenses/syn-3.0.9-license.txt +23 -0
  41. package/third_party_licenses/toml_datetime-1.1.2-license.txt +19 -0
  42. package/third_party_licenses/toml_edit-0.25.17-license.txt +19 -0
  43. package/third_party_licenses/toml_parser-1.1.5-license.txt +19 -0
  44. package/third_party_licenses/winnow-1.0.4-license.txt +18 -0
  45. package/ts/00_commitinfo_data.ts +1 -1
  46. package/ts/classes.dashboard.ts +280 -0
  47. package/ts/dashboard.bundled.ts.third-party-notices.json +1741 -0
  48. package/ts/dashboard.bundled.ts.third-party-notices.txt +5015 -0
  49. package/ts/dashboard.interfaces.ts +148 -0
  50. package/ts/dashboard.plugins.ts +13 -0
  51. package/ts/index.ts +217 -2
package/.smartconfig.json CHANGED
@@ -43,9 +43,27 @@
43
43
  "concurrency": 1,
44
44
  "timeout": 300,
45
45
  "prepare": {
46
- "once": "rsrepo --configured-targets"
46
+ "once": "rsrepo --configured-targets && tsrepo bundle"
47
47
  }
48
48
  },
49
+ "bundle": {
50
+ "bundles": [
51
+ {
52
+ "from": "./ts_web/index.ts",
53
+ "to": "./ts/dashboard.bundled.ts",
54
+ "outputMode": "base64ts",
55
+ "bundler": "esbuild",
56
+ "production": true,
57
+ "sourcemap": false,
58
+ "includeFiles": [
59
+ {
60
+ "from": "./html/index.html",
61
+ "to": "index.html"
62
+ }
63
+ ]
64
+ }
65
+ ]
66
+ },
49
67
  "docs": {
50
68
  "legal": "\n## License and Legal Information\n\nThis repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license.md) file.\n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.\n\nUse of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District Court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
51
69
  }
Binary file
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "format": "tsrust.build-provenance.v2",
3
- "binarySha256": "1980c7bbf44460d25e11566b17e4712b72f5404c112ff7a5afef9a35b162f32c",
3
+ "binarySha256": "cdd1429e14a8decd0c4b9489bc354dcec74ad81bc44e6a8fcdaf2084c2c1ff94",
4
4
  "buildInfo": {
5
5
  "projectName": "@lossless.org/objectstorage",
6
- "projectVersion": "11.0.0",
7
- "gitCommit": "c81d8670c3a4eb21d8b926861ab0276aed7e1344",
6
+ "projectVersion": "11.2.0",
7
+ "gitCommit": "ad4fe239a2844ce6bcca0ea95f51c1f4e24e83e0",
8
8
  "gitDirty": false,
9
- "builtAt": "2026-11-04T21:59:02.812Z",
9
+ "builtAt": "2026-11-05T19:11:09.869Z",
10
10
  "tsrustVersion": "1.1.1",
11
11
  "binary": "ruststorage",
12
12
  "target": "linux_amd64"
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "format": "tsrust.build-provenance.v2",
3
- "binarySha256": "60d85f23387481dcfa616e86e731da9a8fdbac66c9786e26feaa955aec1e8f91",
3
+ "binarySha256": "9f16c05efd8c18dce86483c926052de0a06cea8e98e9a2982f930fc7ef306fbd",
4
4
  "buildInfo": {
5
5
  "projectName": "@lossless.org/objectstorage",
6
- "projectVersion": "11.0.0",
7
- "gitCommit": "c81d8670c3a4eb21d8b926861ab0276aed7e1344",
6
+ "projectVersion": "11.2.0",
7
+ "gitCommit": "ad4fe239a2844ce6bcca0ea95f51c1f4e24e83e0",
8
8
  "gitDirty": false,
9
- "builtAt": "2026-11-04T21:59:04.054Z",
9
+ "builtAt": "2026-11-05T19:11:12.031Z",
10
10
  "tsrustVersion": "1.1.1",
11
11
  "binary": "ruststorage",
12
12
  "target": "linux_amd64_musl"
Binary file
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "format": "tsrust.build-provenance.v2",
3
- "binarySha256": "7c067c7d454c697f2f1f2324a70e68d315fd5705584cb22e34e31d1728de7368",
3
+ "binarySha256": "362b51aae8eda7ada655b3ddadaf787bd89251fb8683ac14f2d237779ba311d4",
4
4
  "buildInfo": {
5
5
  "projectName": "@lossless.org/objectstorage",
6
- "projectVersion": "11.0.0",
7
- "gitCommit": "c81d8670c3a4eb21d8b926861ab0276aed7e1344",
6
+ "projectVersion": "11.2.0",
7
+ "gitCommit": "ad4fe239a2844ce6bcca0ea95f51c1f4e24e83e0",
8
8
  "gitDirty": false,
9
- "builtAt": "2026-11-04T21:59:03.472Z",
9
+ "builtAt": "2026-11-05T19:11:10.877Z",
10
10
  "tsrustVersion": "1.1.1",
11
11
  "binary": "ruststorage",
12
12
  "target": "linux_arm64"
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "format": "tsrust.build-provenance.v2",
3
- "binarySha256": "8978c9b56759428a25399843a2cdbc0f08c56aafc7c315189ba2605ff043a725",
3
+ "binarySha256": "1aa892f80060b4e8e78163d55869324c69698cfa506b0e976978ce813781a5b6",
4
4
  "buildInfo": {
5
5
  "projectName": "@lossless.org/objectstorage",
6
- "projectVersion": "11.0.0",
7
- "gitCommit": "c81d8670c3a4eb21d8b926861ab0276aed7e1344",
6
+ "projectVersion": "11.2.0",
7
+ "gitCommit": "ad4fe239a2844ce6bcca0ea95f51c1f4e24e83e0",
8
8
  "gitDirty": false,
9
- "builtAt": "2026-11-04T21:59:04.554Z",
9
+ "builtAt": "2026-11-05T19:11:12.880Z",
10
10
  "tsrustVersion": "1.1.1",
11
11
  "binary": "ruststorage",
12
12
  "target": "linux_arm64_musl"
Binary file
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "format": "tsrust.build-provenance.v2",
3
- "binarySha256": "7fafb5f1a17fabafae190aafe96e6337636c1cab40566715e5ac15af3caed951",
3
+ "binarySha256": "781d3acefeacd324d1a00a96195cad6edae331176cfdb28e55f7f2cc38b61018",
4
4
  "buildInfo": {
5
5
  "projectName": "@lossless.org/objectstorage",
6
- "projectVersion": "11.0.0",
7
- "gitCommit": "c81d8670c3a4eb21d8b926861ab0276aed7e1344",
6
+ "projectVersion": "11.2.0",
7
+ "gitCommit": "ad4fe239a2844ce6bcca0ea95f51c1f4e24e83e0",
8
8
  "gitDirty": false,
9
- "builtAt": "2026-11-04T22:26:30.568Z",
9
+ "builtAt": "2026-11-05T19:50:02.701Z",
10
10
  "tsrustVersion": "1.1.1",
11
11
  "binary": "ruststorage",
12
12
  "target": "macos_amd64"
Binary file
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "format": "tsrust.build-provenance.v2",
3
- "binarySha256": "b0b608cff5a23cfc2e9afb73539e904c0dcc22902cff02a7b178257431a278ca",
3
+ "binarySha256": "56a95c7bea05728e1a4b1c043bf53e6d78736d682fed9f315ab06a879c2f423c",
4
4
  "buildInfo": {
5
5
  "projectName": "@lossless.org/objectstorage",
6
- "projectVersion": "11.0.0",
7
- "gitCommit": "c81d8670c3a4eb21d8b926861ab0276aed7e1344",
6
+ "projectVersion": "11.2.0",
7
+ "gitCommit": "ad4fe239a2844ce6bcca0ea95f51c1f4e24e83e0",
8
8
  "gitDirty": false,
9
- "builtAt": "2026-11-04T22:26:31.267Z",
9
+ "builtAt": "2026-11-05T19:50:10.132Z",
10
10
  "tsrustVersion": "1.1.1",
11
11
  "binary": "ruststorage",
12
12
  "target": "macos_arm64"
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@lossless.org/objectstorage',
6
- version: '11.0.0',
6
+ version: '11.2.0',
7
7
  description: 'A Node.js TypeScript package to create a local S3-compatible storage server using mapped local directories for development and testing purposes.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSw2QkFBNkI7SUFDbkMsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLGtKQUFrSjtDQUNoSyxDQUFBIn0=
@@ -0,0 +1,49 @@
1
+ import type { IObjectStorageClusterSnapshot } from './dashboard.interfaces.js';
2
+ /** How often the shared sampler asks the engine for a snapshot. */
3
+ export declare const DASHBOARD_SAMPLE_INTERVAL_MS = 2000;
4
+ /** Dashboard sockets admitted at once; the next one is refused. */
5
+ export declare const DASHBOARD_MAXIMUM_CONNECTIONS = 16;
6
+ export interface IObjectStorageDashboardOptions {
7
+ address: string;
8
+ port: number;
9
+ /** Reads one engine snapshot; called by the shared sampler only. */
10
+ readSnapshot: () => Promise<IObjectStorageClusterSnapshot>;
11
+ }
12
+ /**
13
+ * The read-only dashboard: the bundled page plus one TypedSocket on its own
14
+ * port. It reads the engine only through `readSnapshot` (one IPC command),
15
+ * and only while at least one dashboard is connected: one shared sampler
16
+ * every two seconds, one sample in flight, missed ticks skipped. Its router
17
+ * holds one read handler; nothing it serves can change the engine.
18
+ */
19
+ export declare class ObjectStorageDashboard {
20
+ private readonly options;
21
+ private readonly router;
22
+ private readonly typedSocket;
23
+ private readonly smartServe;
24
+ private boundPort;
25
+ private timer;
26
+ private inFlight;
27
+ private latestSample;
28
+ private publishFailureLogged;
29
+ private stopped;
30
+ constructor(optionsArg: IObjectStorageDashboardOptions);
31
+ /** The bound TCP port while running. */
32
+ get port(): number;
33
+ start(): Promise<void>;
34
+ /** Stops the sampler, waits for a sample in flight, then closes every socket. */
35
+ stop(): Promise<void>;
36
+ private connectionCount;
37
+ private addStaticRoutes;
38
+ private startSampler;
39
+ private stopSampler;
40
+ private tick;
41
+ /**
42
+ * Pushes one sample to every dashboard. Never throws: it ends the sampler's
43
+ * promise chain, so a throw here would be an unhandled rejection.
44
+ */
45
+ private publish;
46
+ /** Takes one sample, or joins the one in flight. Never rejects. */
47
+ private takeSample;
48
+ private readSample;
49
+ }
@@ -0,0 +1,234 @@
1
+ import * as plugins from './dashboard.plugins.js';
2
+ import { files as bundledFiles } from './dashboard.bundled.js';
3
+ /** How often the shared sampler asks the engine for a snapshot. */
4
+ export const DASHBOARD_SAMPLE_INTERVAL_MS = 2_000;
5
+ /** Dashboard sockets admitted at once; the next one is refused. */
6
+ export const DASHBOARD_MAXIMUM_CONNECTIONS = 16;
7
+ /** Largest encoded sample pushed; TypedSocket refuses events above 256 KiB. */
8
+ const MAXIMUM_SAMPLE_BYTES = 200 * 1024;
9
+ const DASHBOARD_TAG = 'objectstorage-dashboard';
10
+ const SAMPLE_EVENT = 'objectStorageDashboardSample';
11
+ const contentTypes = {
12
+ '.html': 'text/html; charset=utf-8',
13
+ '.js': 'text/javascript; charset=utf-8',
14
+ '.css': 'text/css; charset=utf-8',
15
+ '.json': 'application/json; charset=utf-8',
16
+ '.txt': 'text/plain; charset=utf-8',
17
+ '.svg': 'image/svg+xml',
18
+ '.woff2': 'font/woff2',
19
+ };
20
+ /**
21
+ * The read-only dashboard: the bundled page plus one TypedSocket on its own
22
+ * port. It reads the engine only through `readSnapshot` (one IPC command),
23
+ * and only while at least one dashboard is connected: one shared sampler
24
+ * every two seconds, one sample in flight, missed ticks skipped. Its router
25
+ * holds one read handler; nothing it serves can change the engine.
26
+ */
27
+ export class ObjectStorageDashboard {
28
+ options;
29
+ router = new plugins.typedrequest.TypedRouter();
30
+ typedSocket;
31
+ smartServe;
32
+ boundPort = 0;
33
+ timer;
34
+ inFlight;
35
+ latestSample;
36
+ publishFailureLogged = false;
37
+ stopped = false;
38
+ constructor(optionsArg) {
39
+ this.options = optionsArg;
40
+ this.router.addTypedHandler(new plugins.typedrequest.TypedHandler('objectStorageDashboardGetSample', async () => this.latestSample ?? (await this.takeSample())));
41
+ this.typedSocket = plugins.typedsocket.TypedSocket.createServer(this.router, {
42
+ onServerConnectionReady: (connection) => {
43
+ this.typedSocket.setServerTag(connection, DASHBOARD_TAG);
44
+ this.startSampler();
45
+ return undefined;
46
+ },
47
+ });
48
+ this.smartServe = new plugins.smartserve.SmartServe({
49
+ port: optionsArg.port,
50
+ hostname: optionsArg.address,
51
+ websocket: {
52
+ typedRouter: this.typedSocket.getServerRoutingSurface(this.router),
53
+ transportOwner: this.typedSocket.webSocketTransportOwner,
54
+ admit: () => {
55
+ if (this.connectionCount() >= DASHBOARD_MAXIMUM_CONNECTIONS) {
56
+ return new Response(`The dashboard admits ${DASHBOARD_MAXIMUM_CONNECTIONS} connections at once.`, { status: 503, headers: { 'Retry-After': '10' } });
57
+ }
58
+ return true;
59
+ },
60
+ onConnectionOpen: (peer) => {
61
+ // Admission and registration are not one step: upgrades admitted
62
+ // together can pass the check before any of them registers.
63
+ if (this.connectionCount() > DASHBOARD_MAXIMUM_CONNECTIONS) {
64
+ peer.close(1013, 'Dashboard connection limit reached');
65
+ }
66
+ },
67
+ },
68
+ });
69
+ this.typedSocket.attachSmartServe(this.smartServe);
70
+ this.addStaticRoutes();
71
+ }
72
+ /** The bound TCP port while running. */
73
+ get port() {
74
+ return this.boundPort;
75
+ }
76
+ async start() {
77
+ const instance = await this.smartServe.start();
78
+ this.boundPort = instance.port;
79
+ }
80
+ /** Stops the sampler, waits for a sample in flight, then closes every socket. */
81
+ async stop() {
82
+ this.stopped = true;
83
+ this.stopSampler();
84
+ if (this.inFlight) {
85
+ await this.inFlight;
86
+ }
87
+ await this.typedSocket.stop();
88
+ await this.smartServe.stop();
89
+ this.boundPort = 0;
90
+ }
91
+ connectionCount() {
92
+ return this.smartServe.getWebSocketConnections().length;
93
+ }
94
+ addStaticRoutes() {
95
+ const index = bundledFiles.find((file) => file.path === 'index.html');
96
+ if (!index) {
97
+ throw new Error('The dashboard bundle has no index.html; run `tsrepo bundle`.');
98
+ }
99
+ const serve = (file) => {
100
+ const body = Buffer.from(file.contentBase64, 'base64');
101
+ const extension = file.path.slice(file.path.lastIndexOf('.'));
102
+ const headers = {
103
+ 'Content-Type': contentTypes[extension] ?? 'application/octet-stream',
104
+ 'Cache-Control': 'no-cache',
105
+ 'X-Content-Type-Options': 'nosniff',
106
+ 'Referrer-Policy': 'no-referrer',
107
+ };
108
+ return () => new Response(body, { status: 200, headers });
109
+ };
110
+ this.smartServe.addRoute('/', 'GET', serve(index));
111
+ for (const file of bundledFiles) {
112
+ this.smartServe.addRoute(`/${file.path}`, 'GET', serve(file));
113
+ }
114
+ }
115
+ startSampler() {
116
+ if (this.timer || this.stopped) {
117
+ return;
118
+ }
119
+ this.timer = setInterval(() => this.tick(), DASHBOARD_SAMPLE_INTERVAL_MS);
120
+ this.tick();
121
+ }
122
+ stopSampler() {
123
+ if (this.timer) {
124
+ clearInterval(this.timer);
125
+ this.timer = undefined;
126
+ }
127
+ }
128
+ tick() {
129
+ if (this.stopped) {
130
+ return;
131
+ }
132
+ if (this.connectionCount() === 0) {
133
+ this.stopSampler();
134
+ this.latestSample = undefined;
135
+ return;
136
+ }
137
+ if (this.inFlight) {
138
+ return;
139
+ }
140
+ void this.takeSample().then((sample) => this.publish(sample));
141
+ }
142
+ /**
143
+ * Pushes one sample to every dashboard. Never throws: it ends the sampler's
144
+ * promise chain, so a throw here would be an unhandled rejection.
145
+ */
146
+ publish(sampleArg) {
147
+ if (this.stopped) {
148
+ return;
149
+ }
150
+ let sampleFailure;
151
+ try {
152
+ this.typedSocket.publishToTag(DASHBOARD_TAG, SAMPLE_EVENT, sampleArg);
153
+ this.publishFailureLogged = false;
154
+ return;
155
+ }
156
+ catch (error) {
157
+ sampleFailure = error;
158
+ }
159
+ // A sample TypedSocket refuses (too large even without peer events)
160
+ // reaches the dashboards as an error instead of silence.
161
+ try {
162
+ this.typedSocket.publishToTag(DASHBOARD_TAG, SAMPLE_EVENT, {
163
+ sampledAt: sampleArg.sampledAt,
164
+ snapshot: null,
165
+ error: `The sample could not be pushed: ${describeError(sampleFailure)}`,
166
+ eventsTruncated: false,
167
+ });
168
+ this.publishFailureLogged = false;
169
+ }
170
+ catch (errorPushFailure) {
171
+ // Neither reached the dashboards, so the process log is the only
172
+ // channel left: once per run of failures, not every tick.
173
+ if (!this.publishFailureLogged) {
174
+ this.publishFailureLogged = true;
175
+ console.error(`objectstorage dashboard: a sample could not be pushed (${describeError(sampleFailure)}),`
176
+ + ` nor its error (${describeError(errorPushFailure)}).`);
177
+ }
178
+ }
179
+ }
180
+ /** Takes one sample, or joins the one in flight. Never rejects. */
181
+ takeSample() {
182
+ if (this.inFlight) {
183
+ return this.inFlight;
184
+ }
185
+ const sample = this.readSample().finally(() => {
186
+ this.inFlight = undefined;
187
+ });
188
+ this.inFlight = sample;
189
+ return sample;
190
+ }
191
+ async readSample() {
192
+ const sampledAt = Date.now();
193
+ let sample;
194
+ try {
195
+ const snapshot = await this.options.readSnapshot();
196
+ sample = fitSample({ sampledAt, snapshot, error: null, eventsTruncated: false });
197
+ }
198
+ catch (error) {
199
+ sample = {
200
+ sampledAt,
201
+ snapshot: null,
202
+ error: describeError(error),
203
+ eventsTruncated: false,
204
+ };
205
+ }
206
+ this.latestSample = sample;
207
+ return sample;
208
+ }
209
+ }
210
+ const describeError = (errorArg) => errorArg instanceof Error ? errorArg.message : String(errorArg);
211
+ /**
212
+ * Keeps a sample within the push limit by halving the events of the peer
213
+ * snapshots until it fits; the local node keeps all of its events.
214
+ */
215
+ const fitSample = (sampleArg) => {
216
+ const encodedBytes = (value) => Buffer.byteLength(JSON.stringify(value));
217
+ const peers = sampleArg.snapshot?.cluster?.peers ?? [];
218
+ let sample = sampleArg;
219
+ while (encodedBytes(sample) > MAXIMUM_SAMPLE_BYTES) {
220
+ const longest = Math.max(0, ...peers.map((peer) => peer.snapshot?.events.length ?? 0));
221
+ if (longest === 0) {
222
+ break;
223
+ }
224
+ const keep = Math.floor(longest / 2);
225
+ for (const peer of peers) {
226
+ if (peer.snapshot && peer.snapshot.events.length > keep) {
227
+ peer.snapshot.events = peer.snapshot.events.slice(peer.snapshot.events.length - keep);
228
+ }
229
+ }
230
+ sample = { ...sample, eventsTruncated: true };
231
+ }
232
+ return sample;
233
+ };
234
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kYXNoYm9hcmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jbGFzc2VzLmRhc2hib2FyZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxLQUFLLElBQUksWUFBWSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFRL0QsbUVBQW1FO0FBQ25FLE1BQU0sQ0FBQyxNQUFNLDRCQUE0QixHQUFHLEtBQUssQ0FBQztBQUNsRCxtRUFBbUU7QUFDbkUsTUFBTSxDQUFDLE1BQU0sNkJBQTZCLEdBQUcsRUFBRSxDQUFDO0FBQ2hELCtFQUErRTtBQUMvRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUM7QUFDeEMsTUFBTSxhQUFhLEdBQUcseUJBQXlCLENBQUM7QUFDaEQsTUFBTSxZQUFZLEdBQWdELDhCQUE4QixDQUFDO0FBRWpHLE1BQU0sWUFBWSxHQUEyQjtJQUMzQyxPQUFPLEVBQUUsMEJBQTBCO0lBQ25DLEtBQUssRUFBRSxnQ0FBZ0M7SUFDdkMsTUFBTSxFQUFFLHlCQUF5QjtJQUNqQyxPQUFPLEVBQUUsaUNBQWlDO0lBQzFDLE1BQU0sRUFBRSwyQkFBMkI7SUFDbkMsTUFBTSxFQUFFLGVBQWU7SUFDdkIsUUFBUSxFQUFFLFlBQVk7Q0FDdkIsQ0FBQztBQVNGOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxzQkFBc0I7SUFDaEIsT0FBTyxDQUFpQztJQUN4QyxNQUFNLEdBQUcsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2hELFdBQVcsQ0FBa0M7SUFDN0MsVUFBVSxDQUFnQztJQUNuRCxTQUFTLEdBQUcsQ0FBQyxDQUFDO0lBQ2QsS0FBSyxDQUE2QztJQUNsRCxRQUFRLENBQXFEO0lBQzdELFlBQVksQ0FBNEM7SUFDeEQsb0JBQW9CLEdBQUcsS0FBSyxDQUFDO0lBQzdCLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFFeEIsWUFBWSxVQUEwQztRQUNwRCxJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQztRQUMxQixJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FDekIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDbkMsaUNBQWlDLEVBQ2pDLEtBQUssSUFBSSxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQzNELENBQ0YsQ0FBQztRQUNGLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDM0UsdUJBQXVCLEVBQUUsQ0FBQyxVQUFVLEVBQUUsRUFBRTtnQkFDdEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsVUFBVSxFQUFFLGFBQWEsQ0FBQyxDQUFDO2dCQUN6RCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3BCLE9BQU8sU0FBUyxDQUFDO1lBQ25CLENBQUM7U0FDRixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7WUFDbEQsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJO1lBQ3JCLFFBQVEsRUFBRSxVQUFVLENBQUMsT0FBTztZQUM1QixTQUFTLEVBQUU7Z0JBQ1QsV0FBVyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztnQkFDbEUsY0FBYyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsdUJBQXVCO2dCQUN4RCxLQUFLLEVBQUUsR0FBRyxFQUFFO29CQUNWLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxJQUFJLDZCQUE2QixFQUFFLENBQUM7d0JBQzVELE9BQU8sSUFBSSxRQUFRLENBQ2pCLHdCQUF3Qiw2QkFBNkIsdUJBQXVCLEVBQzVFLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FDbEQsQ0FBQztvQkFDSixDQUFDO29CQUNELE9BQU8sSUFBSSxDQUFDO2dCQUNkLENBQUM7Z0JBQ0QsZ0JBQWdCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRTtvQkFDekIsaUVBQWlFO29CQUNqRSw0REFBNEQ7b0JBQzVELElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxHQUFHLDZCQUE2QixFQUFFLENBQUM7d0JBQzNELElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLG9DQUFvQyxDQUFDLENBQUM7b0JBQ3pELENBQUM7Z0JBQ0gsQ0FBQzthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbkQsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFFRCx3Q0FBd0M7SUFDeEMsSUFBVyxJQUFJO1FBQ2IsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3hCLENBQUM7SUFFTSxLQUFLLENBQUMsS0FBSztRQUNoQixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDL0MsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDO0lBQ2pDLENBQUM7SUFFRCxpRkFBaUY7SUFDMUUsS0FBSyxDQUFDLElBQUk7UUFDZixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNwQixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkIsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDbEIsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ3RCLENBQUM7UUFDRCxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDOUIsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDO0lBQ3JCLENBQUM7SUFFTyxlQUFlO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDLE1BQU0sQ0FBQztJQUMxRCxDQUFDO0lBRU8sZUFBZTtRQUNyQixNQUFNLEtBQUssR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLFlBQVksQ0FBQyxDQUFDO1FBQ3RFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsOERBQThELENBQUMsQ0FBQztRQUNsRixDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsQ0FBQyxJQUE2QyxFQUFFLEVBQUU7WUFDOUQsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3ZELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDOUQsTUFBTSxPQUFPLEdBQUc7Z0JBQ2QsY0FBYyxFQUFFLFlBQVksQ0FBQyxTQUFTLENBQUMsSUFBSSwwQkFBMEI7Z0JBQ3JFLGVBQWUsRUFBRSxVQUFVO2dCQUMzQix3QkFBd0IsRUFBRSxTQUFTO2dCQUNuQyxpQkFBaUIsRUFBRSxhQUFhO2FBQ2pDLENBQUM7WUFDRixPQUFPLEdBQUcsRUFBRSxDQUFDLElBQUksUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUM1RCxDQUFDLENBQUM7UUFDRixJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ25ELEtBQUssTUFBTSxJQUFJLElBQUksWUFBWSxFQUFFLENBQUM7WUFDaEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ2hFLENBQUM7SUFDSCxDQUFDO0lBRU8sWUFBWTtRQUNsQixJQUFJLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQy9CLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLDRCQUE0QixDQUFDLENBQUM7UUFDMUUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUVPLFdBQVc7UUFDakIsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDZixhQUFhLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzFCLElBQUksQ0FBQyxLQUFLLEdBQUcsU0FBUyxDQUFDO1FBQ3pCLENBQUM7SUFDSCxDQUFDO0lBRU8sSUFBSTtRQUNWLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pCLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDakMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxZQUFZLEdBQUcsU0FBUyxDQUFDO1lBQzlCLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDbEIsT0FBTztRQUNULENBQUM7UUFDRCxLQUFLLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssT0FBTyxDQUFDLFNBQXdDO1FBQ3RELElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pCLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxhQUFzQixDQUFDO1FBQzNCLElBQUksQ0FBQztZQUNILElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUMzQixhQUFhLEVBQ2IsWUFBWSxFQUNaLFNBQVMsQ0FDVixDQUFDO1lBQ0YsSUFBSSxDQUFDLG9CQUFvQixHQUFHLEtBQUssQ0FBQztZQUNsQyxPQUFPO1FBQ1QsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQ3hCLENBQUM7UUFDRCxvRUFBb0U7UUFDcEUseURBQXlEO1FBQ3pELElBQUksQ0FBQztZQUNILElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUMzQixhQUFhLEVBQ2IsWUFBWSxFQUNaO2dCQUNFLFNBQVMsRUFBRSxTQUFTLENBQUMsU0FBUztnQkFDOUIsUUFBUSxFQUFFLElBQUk7Z0JBQ2QsS0FBSyxFQUFFLG1DQUFtQyxhQUFhLENBQUMsYUFBYSxDQUFDLEVBQUU7Z0JBQ3hFLGVBQWUsRUFBRSxLQUFLO2FBQ3ZCLENBQ0YsQ0FBQztZQUNGLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxLQUFLLENBQUM7UUFDcEMsQ0FBQztRQUFDLE9BQU8sZ0JBQWdCLEVBQUUsQ0FBQztZQUMxQixpRUFBaUU7WUFDakUsMERBQTBEO1lBQzFELElBQUksQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztnQkFDL0IsSUFBSSxDQUFDLG9CQUFvQixHQUFHLElBQUksQ0FBQztnQkFDakMsT0FBTyxDQUFDLEtBQUssQ0FDWCwwREFBMEQsYUFBYSxDQUFDLGFBQWEsQ0FBQyxJQUFJO3NCQUN0RixtQkFBbUIsYUFBYSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FDM0QsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELG1FQUFtRTtJQUMzRCxVQUFVO1FBQ2hCLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2xCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUN2QixDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUU7WUFDNUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxTQUFTLENBQUM7UUFDNUIsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQztRQUN2QixPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU8sS0FBSyxDQUFDLFVBQVU7UUFDdEIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQzdCLElBQUksTUFBcUMsQ0FBQztRQUMxQyxJQUFJLENBQUM7WUFDSCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDbkQsTUFBTSxHQUFHLFNBQVMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNuRixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sR0FBRztnQkFDUCxTQUFTO2dCQUNULFFBQVEsRUFBRSxJQUFJO2dCQUNkLEtBQUssRUFBRSxhQUFhLENBQUMsS0FBSyxDQUFDO2dCQUMzQixlQUFlLEVBQUUsS0FBSzthQUN2QixDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksQ0FBQyxZQUFZLEdBQUcsTUFBTSxDQUFDO1FBQzNCLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7Q0FDRjtBQUVELE1BQU0sYUFBYSxHQUFHLENBQUMsUUFBaUIsRUFBVSxFQUFFLENBQ2xELFFBQVEsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUVsRTs7O0dBR0c7QUFDSCxNQUFNLFNBQVMsR0FBRyxDQUFDLFNBQXdDLEVBQWlDLEVBQUU7SUFDNUYsTUFBTSxZQUFZLEdBQUcsQ0FBQyxLQUFvQyxFQUFFLEVBQUUsQ0FDNUQsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDM0MsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQztJQUN2RCxJQUFJLE1BQU0sR0FBRyxTQUFTLENBQUM7SUFDdkIsT0FBTyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsb0JBQW9CLEVBQUUsQ0FBQztRQUNuRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZGLElBQUksT0FBTyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ2xCLE1BQU07UUFDUixDQUFDO1FBQ0QsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDckMsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN6QixJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLElBQUksRUFBRSxDQUFDO2dCQUN4RCxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxDQUFDO1lBQ3hGLENBQUM7UUFDSCxDQUFDO1FBQ0QsTUFBTSxHQUFHLEVBQUUsR0FBRyxNQUFNLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBRSxDQUFDO0lBQ2hELENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDLENBQUMifQ==
@@ -0,0 +1,4 @@
1
+ export declare const files: {
2
+ path: string;
3
+ contentBase64: string;
4
+ }[];