@ardrive/turbo-sdk 1.25.0 → 1.26.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 +170 -62
- package/bundles/web.bundle.min.js +1584 -730
- package/lib/cjs/common/events.js +256 -0
- package/lib/cjs/common/events.test.js +470 -0
- package/lib/cjs/common/http.js +4 -13
- package/lib/cjs/common/turbo.js +6 -4
- package/lib/cjs/common/upload.js +65 -37
- package/lib/cjs/node/signer.js +30 -11
- package/lib/cjs/node/upload.js +7 -1
- package/lib/cjs/utils/axiosClient.js +3 -0
- package/lib/cjs/utils/readableStream.js +15 -0
- package/lib/cjs/version.js +1 -1
- package/lib/cjs/web/signer.js +55 -28
- package/lib/esm/common/events.js +249 -0
- package/lib/esm/common/events.test.js +468 -0
- package/lib/esm/common/http.js +4 -13
- package/lib/esm/common/turbo.js +6 -4
- package/lib/esm/common/upload.js +66 -38
- package/lib/esm/node/signer.js +30 -11
- package/lib/esm/node/upload.js +7 -1
- package/lib/esm/utils/axiosClient.js +3 -0
- package/lib/esm/utils/readableStream.js +15 -0
- package/lib/esm/version.js +1 -1
- package/lib/esm/web/signer.js +55 -28
- package/lib/types/common/events.d.ts +56 -0
- package/lib/types/common/events.d.ts.map +1 -0
- package/lib/types/common/events.test.d.ts +2 -0
- package/lib/types/common/events.test.d.ts.map +1 -0
- package/lib/types/common/http.d.ts +1 -2
- package/lib/types/common/http.d.ts.map +1 -1
- package/lib/types/common/signer.d.ts +1 -1
- package/lib/types/common/signer.d.ts.map +1 -1
- package/lib/types/common/turbo.d.ts +4 -4
- package/lib/types/common/turbo.d.ts.map +1 -1
- package/lib/types/common/upload.d.ts +13 -5
- package/lib/types/common/upload.d.ts.map +1 -1
- package/lib/types/node/signer.d.ts +1 -1
- package/lib/types/node/signer.d.ts.map +1 -1
- package/lib/types/node/upload.d.ts.map +1 -1
- package/lib/types/types.d.ts +61 -7
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/utils/axiosClient.d.ts.map +1 -1
- package/lib/types/utils/readableStream.d.ts +0 -1
- package/lib/types/utils/readableStream.d.ts.map +1 -1
- package/lib/types/version.d.ts +1 -1
- package/lib/types/web/signer.d.ts +1 -1
- package/lib/types/web/signer.d.ts.map +1 -1
- package/package.json +9 -7
@@ -0,0 +1,256 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.TurboEventEmitter = void 0;
|
4
|
+
exports.createStreamWithEvents = createStreamWithEvents;
|
5
|
+
exports.createStreamWithUploadEvents = createStreamWithUploadEvents;
|
6
|
+
exports.createStreamWithSigningEvents = createStreamWithSigningEvents;
|
7
|
+
/**
|
8
|
+
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
9
|
+
*
|
10
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
11
|
+
* you may not use this file except in compliance with the License.
|
12
|
+
* You may obtain a copy of the License at
|
13
|
+
*
|
14
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
15
|
+
*
|
16
|
+
* Unless required by applicable law or agreed to in writing, software
|
17
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
18
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
19
|
+
* See the License for the specific language governing permissions and
|
20
|
+
* limitations under the License.
|
21
|
+
*/
|
22
|
+
const eventemitter3_1 = require("eventemitter3");
|
23
|
+
const stream_1 = require("stream");
|
24
|
+
/**
|
25
|
+
* Creates a ReadableStream with events that emits progress and error events using the event names map.
|
26
|
+
*
|
27
|
+
* E.g.
|
28
|
+
*
|
29
|
+
* ```ts
|
30
|
+
* const eventNamesMap = {
|
31
|
+
* 'on-progress': 'signing-progress', // emits 'signing-progress' on event progress
|
32
|
+
* 'on-error': 'signing-error', // emits 'signing-error' errors
|
33
|
+
* 'on-end': 'signing-success', // emits 'signing-success' on end
|
34
|
+
* };
|
35
|
+
*
|
36
|
+
* const streamWithEvents = createStreamWithEvents({
|
37
|
+
* data,
|
38
|
+
* dataSize,
|
39
|
+
* emitter,
|
40
|
+
* eventNamesMap,
|
41
|
+
* });
|
42
|
+
* ```
|
43
|
+
*/
|
44
|
+
function createReadableStreamWithEvents({ data, dataSize, emitter, eventNamesMap, }) {
|
45
|
+
const originalStream = data instanceof ReadableStream
|
46
|
+
? data
|
47
|
+
: new ReadableStream({
|
48
|
+
start: (controller) => {
|
49
|
+
controller.enqueue(data);
|
50
|
+
controller.close();
|
51
|
+
},
|
52
|
+
});
|
53
|
+
let processedBytes = 0;
|
54
|
+
let reader;
|
55
|
+
const stream = new ReadableStream({
|
56
|
+
start() {
|
57
|
+
reader = originalStream.getReader();
|
58
|
+
},
|
59
|
+
async pull(controller) {
|
60
|
+
try {
|
61
|
+
const { value, done } = await reader.read();
|
62
|
+
if (done) {
|
63
|
+
emitter.emit(eventNamesMap['on-end']);
|
64
|
+
controller.close();
|
65
|
+
return;
|
66
|
+
}
|
67
|
+
processedBytes += value.length;
|
68
|
+
emitter.emit(eventNamesMap['on-progress'], {
|
69
|
+
processedBytes,
|
70
|
+
totalBytes: dataSize,
|
71
|
+
});
|
72
|
+
controller.enqueue(value);
|
73
|
+
}
|
74
|
+
catch (error) {
|
75
|
+
emitter.emit(eventNamesMap['on-error'], error);
|
76
|
+
controller.error(error);
|
77
|
+
}
|
78
|
+
},
|
79
|
+
cancel(reason) {
|
80
|
+
return reader.cancel(reason);
|
81
|
+
},
|
82
|
+
});
|
83
|
+
return {
|
84
|
+
stream,
|
85
|
+
resume: () => void 0, // not needed for ReadableStreams but stubbed out for type compatibility
|
86
|
+
};
|
87
|
+
}
|
88
|
+
/**
|
89
|
+
* Creates an eventing Readable stream that emits progress and error events.
|
90
|
+
*
|
91
|
+
* NOTE: When dealing ith Readable streams, any downstream consumer stream will need to call `resume()` once the consumer is properly set up.
|
92
|
+
* If we were to call it internally here, bytes would start flowing due to the configured 'data' event listener.
|
93
|
+
* For ReadableStreams, this is not a concern, so we stub out the resume function
|
94
|
+
*
|
95
|
+
* Example usage:
|
96
|
+
*
|
97
|
+
* ```ts
|
98
|
+
* const { stream, resume } = createReadableWithEvents({
|
99
|
+
* data,
|
100
|
+
* dataSize,
|
101
|
+
* emitter,
|
102
|
+
* eventNamesMap,
|
103
|
+
* });
|
104
|
+
*
|
105
|
+
* // setup any promise that will consume the stream (e.g. a POST request)
|
106
|
+
* const promise = new Promise((resolve, reject) => {
|
107
|
+
* stream.on('data', (chunk) => {
|
108
|
+
* resolve(chunk);
|
109
|
+
* });
|
110
|
+
* });
|
111
|
+
*
|
112
|
+
* // allow bytes to start flowing so the promise gets the data
|
113
|
+
* resume();
|
114
|
+
*
|
115
|
+
* // wait for the promise to resolve
|
116
|
+
* const result = await promise;
|
117
|
+
* ```
|
118
|
+
*/
|
119
|
+
function createReadableWithEvents({ data, dataSize, emitter, eventNamesMap, }) {
|
120
|
+
const existingStream = data instanceof stream_1.Readable ? data : stream_1.Readable.from(data);
|
121
|
+
const eventingStream = new stream_1.PassThrough();
|
122
|
+
// pause the stream to avoid emitting progress events until the stream is ready
|
123
|
+
existingStream.pause();
|
124
|
+
// add listener to emit progress events as the stream is read
|
125
|
+
let processedBytes = 0;
|
126
|
+
existingStream.on('data', (chunk) => {
|
127
|
+
eventingStream.write(chunk);
|
128
|
+
processedBytes += chunk.length;
|
129
|
+
emitter.emit(eventNamesMap['on-progress'], {
|
130
|
+
processedBytes,
|
131
|
+
totalBytes: dataSize,
|
132
|
+
});
|
133
|
+
});
|
134
|
+
existingStream.on('end', () => {
|
135
|
+
emitter.emit(eventNamesMap['on-end']);
|
136
|
+
eventingStream.end();
|
137
|
+
});
|
138
|
+
existingStream.on('error', (error) => {
|
139
|
+
emitter.emit(eventNamesMap['on-error'], error);
|
140
|
+
eventingStream.destroy(error);
|
141
|
+
});
|
142
|
+
return {
|
143
|
+
stream: eventingStream,
|
144
|
+
// allows bytes to start flowing from the original stream when the consumer is ready
|
145
|
+
resume: () => existingStream.resume(),
|
146
|
+
};
|
147
|
+
}
|
148
|
+
/**
|
149
|
+
* Creates an eventing stream from the input data that emits progress and error events
|
150
|
+
*/
|
151
|
+
function createStreamWithEvents({ data, dataSize, emitter, eventNamesMap, }) {
|
152
|
+
if (data instanceof ReadableStream ||
|
153
|
+
(typeof window !== 'undefined' && data instanceof Buffer)) {
|
154
|
+
return createReadableStreamWithEvents({
|
155
|
+
data,
|
156
|
+
dataSize,
|
157
|
+
emitter,
|
158
|
+
eventNamesMap,
|
159
|
+
});
|
160
|
+
}
|
161
|
+
if (data instanceof stream_1.Readable || data instanceof Buffer) {
|
162
|
+
return createReadableWithEvents({
|
163
|
+
data,
|
164
|
+
dataSize,
|
165
|
+
emitter,
|
166
|
+
eventNamesMap,
|
167
|
+
});
|
168
|
+
}
|
169
|
+
throw new Error('Invalid data or platform type');
|
170
|
+
}
|
171
|
+
class TurboEventEmitter extends eventemitter3_1.EventEmitter {
|
172
|
+
constructor({ onProgress, onError, onSuccess, onUploadProgress, onUploadError, onUploadSuccess, onSigningProgress, onSigningError, onSigningSuccess, } = {}) {
|
173
|
+
super();
|
174
|
+
if (onUploadProgress !== undefined) {
|
175
|
+
this.on('upload-progress', onUploadProgress);
|
176
|
+
}
|
177
|
+
if (onUploadError !== undefined) {
|
178
|
+
this.on('upload-error', onUploadError);
|
179
|
+
}
|
180
|
+
if (onUploadSuccess !== undefined) {
|
181
|
+
this.on('upload-success', onUploadSuccess);
|
182
|
+
}
|
183
|
+
if (onSigningProgress !== undefined) {
|
184
|
+
this.on('signing-progress', onSigningProgress);
|
185
|
+
}
|
186
|
+
if (onSigningError !== undefined) {
|
187
|
+
this.on('signing-error', onSigningError);
|
188
|
+
}
|
189
|
+
if (onSigningSuccess !== undefined) {
|
190
|
+
this.on('signing-success', onSigningSuccess);
|
191
|
+
}
|
192
|
+
if (onProgress !== undefined) {
|
193
|
+
this.on('overall-progress', onProgress);
|
194
|
+
}
|
195
|
+
if (onError !== undefined) {
|
196
|
+
this.on('overall-error', onError);
|
197
|
+
}
|
198
|
+
if (onSuccess !== undefined) {
|
199
|
+
this.on('overall-success', onSuccess);
|
200
|
+
}
|
201
|
+
// emit listeners for total events
|
202
|
+
this.on('signing-progress', (event) => {
|
203
|
+
this.emit('overall-progress', {
|
204
|
+
...event,
|
205
|
+
processedBytes: event.processedBytes / 2, // since the total progress requires 2 passes through the stream, signing progress is only half of the total progress
|
206
|
+
totalBytes: event.totalBytes,
|
207
|
+
step: 'signing',
|
208
|
+
});
|
209
|
+
});
|
210
|
+
this.on('signing-error', (error) => {
|
211
|
+
this.emit('overall-error', error);
|
212
|
+
});
|
213
|
+
this.on('upload-progress', (event) => {
|
214
|
+
this.emit('overall-progress', {
|
215
|
+
...event,
|
216
|
+
processedBytes: event.totalBytes / 2 + event.processedBytes / 2, // Start at 50% since signing is done, then add half of upload progress
|
217
|
+
totalBytes: event.totalBytes,
|
218
|
+
step: 'upload',
|
219
|
+
});
|
220
|
+
});
|
221
|
+
this.on('upload-error', (error) => {
|
222
|
+
this.emit('overall-error', error);
|
223
|
+
});
|
224
|
+
// NOTE: this is the last event emitted for successful upload,
|
225
|
+
// if another step was added (e.g. verifying optimistic caching)
|
226
|
+
// then this overall-success event will be emitted after that step
|
227
|
+
this.on('upload-success', () => {
|
228
|
+
this.emit('overall-success');
|
229
|
+
});
|
230
|
+
}
|
231
|
+
}
|
232
|
+
exports.TurboEventEmitter = TurboEventEmitter;
|
233
|
+
function createStreamWithUploadEvents({ data, dataSize, emitter = new TurboEventEmitter(), }) {
|
234
|
+
return createStreamWithEvents({
|
235
|
+
data,
|
236
|
+
dataSize,
|
237
|
+
emitter,
|
238
|
+
eventNamesMap: {
|
239
|
+
'on-progress': 'upload-progress',
|
240
|
+
'on-error': 'upload-error',
|
241
|
+
'on-end': 'upload-success',
|
242
|
+
},
|
243
|
+
});
|
244
|
+
}
|
245
|
+
function createStreamWithSigningEvents({ data, dataSize, emitter = new TurboEventEmitter(), }) {
|
246
|
+
return createStreamWithEvents({
|
247
|
+
data,
|
248
|
+
dataSize,
|
249
|
+
emitter,
|
250
|
+
eventNamesMap: {
|
251
|
+
'on-progress': 'signing-progress',
|
252
|
+
'on-error': 'signing-error',
|
253
|
+
'on-end': 'signing-success',
|
254
|
+
},
|
255
|
+
});
|
256
|
+
}
|