@heyputer/puter.js 2.1.6 → 2.1.7
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/dist/puter.cjs +2 -2
- package/index.d.ts +14 -14
- package/package.json +1 -1
- package/src/index.js +91 -91
- package/src/lib/APICallLogger.js +20 -21
- package/src/lib/EventListener.js +10 -10
- package/src/lib/filesystem/APIFS.js +11 -19
- package/src/lib/filesystem/CacheFS.js +25 -25
- package/src/lib/filesystem/PostMessageFS.js +11 -11
- package/src/lib/filesystem/definitions.js +11 -10
- package/src/lib/path.js +505 -446
- package/src/lib/polyfills/fileReaderPoly.js +40 -0
- package/src/lib/polyfills/localStorage.js +30 -33
- package/src/lib/polyfills/xhrshim.js +206 -207
- package/src/lib/utils.js +160 -151
- package/src/lib/xdrpc.js +9 -9
- package/src/modules/AI.js +416 -290
- package/src/modules/Apps.js +56 -56
- package/src/modules/Auth.js +17 -17
- package/src/modules/Debug.js +1 -1
- package/src/modules/Drivers.js +41 -41
- package/src/modules/FSItem.js +64 -62
- package/src/modules/FileSystem/index.js +22 -23
- package/src/modules/FileSystem/operations/copy.js +7 -7
- package/src/modules/FileSystem/operations/deleteFSEntry.js +14 -12
- package/src/modules/FileSystem/operations/getReadUrl.js +16 -14
- package/src/modules/FileSystem/operations/mkdir.js +11 -11
- package/src/modules/FileSystem/operations/move.js +12 -12
- package/src/modules/FileSystem/operations/read.js +10 -10
- package/src/modules/FileSystem/operations/readdir.js +28 -28
- package/src/modules/FileSystem/operations/rename.js +11 -11
- package/src/modules/FileSystem/operations/sign.js +33 -30
- package/src/modules/FileSystem/operations/space.js +7 -7
- package/src/modules/FileSystem/operations/stat.js +25 -25
- package/src/modules/FileSystem/operations/symlink.js +15 -17
- package/src/modules/FileSystem/operations/upload.js +151 -122
- package/src/modules/FileSystem/operations/write.js +16 -12
- package/src/modules/FileSystem/utils/getAbsolutePathForApp.js +10 -6
- package/src/modules/Hosting.js +29 -29
- package/src/modules/KV.js +23 -23
- package/src/modules/OS.js +15 -15
- package/src/modules/Perms.js +19 -21
- package/src/modules/PuterDialog.js +46 -48
- package/src/modules/Threads.js +17 -20
- package/src/modules/UI.js +156 -156
- package/src/modules/Util.js +3 -3
- package/src/modules/Workers.js +52 -49
- package/src/modules/networking/PSocket.js +38 -38
- package/src/modules/networking/PTLS.js +54 -47
- package/src/modules/networking/PWispHandler.js +49 -47
- package/src/modules/networking/parsers.js +110 -108
- package/src/modules/networking/requests.js +67 -78
- package/src/services/APIAccess.js +9 -9
- package/src/services/FSRelay.js +6 -6
- package/src/services/Filesystem.js +8 -8
- package/src/services/NoPuterYet.js +2 -2
- package/src/services/XDIncoming.js +1 -1
package/src/lib/utils.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { FileReaderPoly } from "./polyfills/fileReaderPoly.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Parses a given response text into a JSON object. If the parsing fails due to invalid JSON format,
|
|
3
5
|
* the original response text is returned.
|
|
@@ -12,7 +14,7 @@
|
|
|
12
14
|
* // returns "Invalid JSON"
|
|
13
15
|
* parseResponse('Invalid JSON');
|
|
14
16
|
*/
|
|
15
|
-
async function parseResponse(target) {
|
|
17
|
+
async function parseResponse (target) {
|
|
16
18
|
if ( target.responseType === 'blob' ) {
|
|
17
19
|
// Get content type of the blob
|
|
18
20
|
const contentType = target.getResponseHeader('content-type');
|
|
@@ -21,10 +23,10 @@ async function parseResponse(target) {
|
|
|
21
23
|
const text = await target.response.text();
|
|
22
24
|
try {
|
|
23
25
|
return JSON.parse(text);
|
|
24
|
-
} catch (error) {
|
|
26
|
+
} catch ( error ) {
|
|
25
27
|
return text;
|
|
26
28
|
}
|
|
27
|
-
}else if ( contentType.startsWith('application/octet-stream') ) {
|
|
29
|
+
} else if ( contentType.startsWith('application/octet-stream') ) {
|
|
28
30
|
// If the blob is an octet stream, return the blob
|
|
29
31
|
return target.response;
|
|
30
32
|
}
|
|
@@ -38,33 +40,31 @@ async function parseResponse(target) {
|
|
|
38
40
|
const responseText = target.responseText;
|
|
39
41
|
try {
|
|
40
42
|
return JSON.parse(responseText);
|
|
41
|
-
} catch (error) {
|
|
43
|
+
} catch ( error ) {
|
|
42
44
|
return responseText;
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
/**
|
|
47
|
-
* A function that generates a UUID (Universally Unique Identifier) using the version 4 format,
|
|
49
|
+
* A function that generates a UUID (Universally Unique Identifier) using the version 4 format,
|
|
48
50
|
* which are random UUIDs. It uses the cryptographic number generator available in modern browsers.
|
|
49
51
|
*
|
|
50
|
-
* The generated UUID is a 36 character string (32 alphanumeric characters separated by 4 hyphens).
|
|
51
|
-
* It follows the pattern: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, where x is any hexadecimal digit
|
|
52
|
+
* The generated UUID is a 36 character string (32 alphanumeric characters separated by 4 hyphens).
|
|
53
|
+
* It follows the pattern: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, where x is any hexadecimal digit
|
|
52
54
|
* and y is one of 8, 9, A, or B.
|
|
53
55
|
*
|
|
54
56
|
* @returns {string} Returns a new UUID v4 string.
|
|
55
57
|
*
|
|
56
58
|
* @example
|
|
57
|
-
*
|
|
59
|
+
*
|
|
58
60
|
* let id = this.#uuidv4(); // Generate a new UUID
|
|
59
|
-
*
|
|
61
|
+
*
|
|
60
62
|
*/
|
|
61
|
-
function uuidv4(){
|
|
63
|
+
function uuidv4 () {
|
|
62
64
|
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
|
|
63
|
-
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
|
64
|
-
);
|
|
65
|
+
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
|
|
68
68
|
/**
|
|
69
69
|
* Initializes and returns an XMLHttpRequest object configured for a specific API endpoint, method, and headers.
|
|
70
70
|
*
|
|
@@ -77,30 +77,32 @@ function uuidv4(){
|
|
|
77
77
|
*
|
|
78
78
|
* @returns {XMLHttpRequest} The initialized XMLHttpRequest object.
|
|
79
79
|
*/
|
|
80
|
-
function initXhr(endpoint, APIOrigin, authToken, method=
|
|
80
|
+
function initXhr (endpoint, APIOrigin, authToken, method = 'post', contentType = 'text/plain;actually=json', responseType = undefined) {
|
|
81
81
|
const xhr = new XMLHttpRequest();
|
|
82
82
|
xhr.open(method, APIOrigin + endpoint, true);
|
|
83
|
-
if (authToken)
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
if ( authToken )
|
|
84
|
+
{
|
|
85
|
+
xhr.setRequestHeader('Authorization', `Bearer ${ authToken}`);
|
|
86
|
+
}
|
|
87
|
+
xhr.setRequestHeader('Content-Type', contentType);
|
|
86
88
|
xhr.responseType = responseType ?? '';
|
|
87
|
-
|
|
89
|
+
|
|
88
90
|
// Add API call logging if available
|
|
89
|
-
if (globalThis.puter?.apiCallLogger?.isEnabled()) {
|
|
91
|
+
if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
|
|
90
92
|
xhr._puterRequestId = {
|
|
91
93
|
method,
|
|
92
94
|
service: 'xhr',
|
|
93
95
|
operation: endpoint.replace(/^\//, ''),
|
|
94
|
-
params: { endpoint, contentType, responseType }
|
|
96
|
+
params: { endpoint, contentType, responseType },
|
|
95
97
|
};
|
|
96
98
|
}
|
|
97
|
-
|
|
99
|
+
|
|
98
100
|
return xhr;
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
/**
|
|
102
104
|
* Handles an HTTP response by invoking appropriate callback functions and resolving or rejecting a promise.
|
|
103
|
-
*
|
|
105
|
+
*
|
|
104
106
|
* @param {Function} success_cb - An optional callback function for successful responses. It should take a response object
|
|
105
107
|
* as its only argument.
|
|
106
108
|
* @param {Function} error_cb - An optional callback function for error handling. It should take an error object
|
|
@@ -111,41 +113,47 @@ function initXhr(endpoint, APIOrigin, authToken, method= "post", contentType = "
|
|
|
111
113
|
* as its only argument.
|
|
112
114
|
* @param {Object} response - The HTTP response object from the request. Expected to have 'status' and 'responseText'
|
|
113
115
|
* properties.
|
|
114
|
-
*
|
|
116
|
+
*
|
|
115
117
|
* @returns {void} The function does not return a value but will either resolve or reject a promise based on the
|
|
116
118
|
* response status.
|
|
117
119
|
*/
|
|
118
|
-
async function handle_resp(success_cb, error_cb, resolve_func, reject_func, response){
|
|
120
|
+
async function handle_resp (success_cb, error_cb, resolve_func, reject_func, response) {
|
|
119
121
|
const resp = await parseResponse(response);
|
|
120
122
|
// error - unauthorized
|
|
121
|
-
if(response.status === 401){
|
|
123
|
+
if ( response.status === 401 ) {
|
|
122
124
|
// if error callback is provided, call it
|
|
123
|
-
if(error_cb && typeof error_cb === 'function')
|
|
124
|
-
|
|
125
|
+
if ( error_cb && typeof error_cb === 'function' )
|
|
126
|
+
{
|
|
127
|
+
error_cb({ status: 401, message: 'Unauthorized' });
|
|
128
|
+
}
|
|
125
129
|
// reject promise
|
|
126
|
-
return reject_func({status: 401, message: 'Unauthorized'})
|
|
130
|
+
return reject_func({ status: 401, message: 'Unauthorized' });
|
|
127
131
|
}
|
|
128
132
|
// error - other
|
|
129
|
-
else if(response.status !== 200){
|
|
133
|
+
else if ( response.status !== 200 ) {
|
|
130
134
|
// if error callback is provided, call it
|
|
131
|
-
if(error_cb && typeof error_cb === 'function')
|
|
132
|
-
|
|
135
|
+
if ( error_cb && typeof error_cb === 'function' )
|
|
136
|
+
{
|
|
137
|
+
error_cb(resp);
|
|
138
|
+
}
|
|
133
139
|
// reject promise
|
|
134
|
-
return reject_func(resp)
|
|
140
|
+
return reject_func(resp);
|
|
135
141
|
}
|
|
136
142
|
// success
|
|
137
|
-
else{
|
|
143
|
+
else {
|
|
138
144
|
// This is a driver error
|
|
139
|
-
if(resp.success === false && resp.error?.code === 'permission_denied'){
|
|
140
|
-
let perm = await puter.ui.requestPermission({permission: 'driver:puter-image-generation:generate'});
|
|
145
|
+
if ( resp.success === false && resp.error?.code === 'permission_denied' ) {
|
|
146
|
+
let perm = await puter.ui.requestPermission({ permission: 'driver:puter-image-generation:generate' });
|
|
141
147
|
// try sending again if permission was granted
|
|
142
|
-
if(perm.granted){
|
|
148
|
+
if ( perm.granted ) {
|
|
143
149
|
// todo repeat request
|
|
144
150
|
}
|
|
145
151
|
}
|
|
146
152
|
// if success callback is provided, call it
|
|
147
|
-
if(success_cb && typeof success_cb === 'function')
|
|
153
|
+
if ( success_cb && typeof success_cb === 'function' )
|
|
154
|
+
{
|
|
148
155
|
success_cb(resp);
|
|
156
|
+
}
|
|
149
157
|
// resolve with success
|
|
150
158
|
return resolve_func(resp);
|
|
151
159
|
}
|
|
@@ -153,59 +161,62 @@ async function handle_resp(success_cb, error_cb, resolve_func, reject_func, resp
|
|
|
153
161
|
|
|
154
162
|
/**
|
|
155
163
|
* Handles an error by invoking a specified error callback and then rejecting a promise.
|
|
156
|
-
*
|
|
164
|
+
*
|
|
157
165
|
* @param {Function} error_cb - An optional callback function that is called if it's provided.
|
|
158
166
|
* This function should take an error object as its only argument.
|
|
159
167
|
* @param {Function} reject_func - A function used to reject a promise. It should take an error object
|
|
160
168
|
* as its only argument.
|
|
161
169
|
* @param {Object} error - The error object that is passed to both the error callback and the reject function.
|
|
162
|
-
*
|
|
170
|
+
*
|
|
163
171
|
* @returns {void} The function does not return a value but will call the reject function with the error.
|
|
164
172
|
*/
|
|
165
|
-
function handle_error(error_cb, reject_func, error){
|
|
173
|
+
function handle_error (error_cb, reject_func, error) {
|
|
166
174
|
// if error callback is provided, call it
|
|
167
|
-
if(error_cb && typeof error_cb === 'function')
|
|
168
|
-
|
|
175
|
+
if ( error_cb && typeof error_cb === 'function' )
|
|
176
|
+
{
|
|
177
|
+
error_cb(error);
|
|
178
|
+
}
|
|
169
179
|
// reject promise
|
|
170
|
-
return reject_func(error)
|
|
180
|
+
return reject_func(error);
|
|
171
181
|
}
|
|
172
182
|
|
|
173
|
-
function setupXhrEventHandlers(xhr, success_cb, error_cb, resolve_func, reject_func) {
|
|
183
|
+
function setupXhrEventHandlers (xhr, success_cb, error_cb, resolve_func, reject_func) {
|
|
174
184
|
// load: success or error
|
|
175
|
-
xhr.addEventListener('load', async function(e){
|
|
185
|
+
xhr.addEventListener('load', async function (e) {
|
|
176
186
|
// Log the response if API logging is enabled
|
|
177
|
-
if (globalThis.puter?.apiCallLogger?.isEnabled() && this._puterRequestId) {
|
|
187
|
+
if ( globalThis.puter?.apiCallLogger?.isEnabled() && this._puterRequestId ) {
|
|
178
188
|
const response = await parseResponse(this).catch(() => null);
|
|
179
189
|
globalThis.puter.apiCallLogger.logRequest({
|
|
180
190
|
service: this._puterRequestId.service,
|
|
181
191
|
operation: this._puterRequestId.operation,
|
|
182
192
|
params: this._puterRequestId.params,
|
|
183
193
|
result: this.status >= 400 ? null : response,
|
|
184
|
-
error: this.status >= 400 ? { message: this.statusText, status: this.status } : null
|
|
194
|
+
error: this.status >= 400 ? { message: this.statusText, status: this.status } : null,
|
|
185
195
|
});
|
|
186
196
|
}
|
|
187
197
|
return handle_resp(success_cb, error_cb, resolve_func, reject_func, this, xhr);
|
|
188
198
|
});
|
|
189
199
|
|
|
190
200
|
// error
|
|
191
|
-
xhr.addEventListener('error', function(e){
|
|
201
|
+
xhr.addEventListener('error', function (e) {
|
|
192
202
|
// Log the error if API logging is enabled
|
|
193
|
-
if (globalThis.puter?.apiCallLogger?.isEnabled() && this._puterRequestId) {
|
|
203
|
+
if ( globalThis.puter?.apiCallLogger?.isEnabled() && this._puterRequestId ) {
|
|
194
204
|
globalThis.puter.apiCallLogger.logRequest({
|
|
195
205
|
service: this._puterRequestId.service,
|
|
196
206
|
operation: this._puterRequestId.operation,
|
|
197
207
|
params: this._puterRequestId.params,
|
|
198
208
|
error: {
|
|
199
209
|
message: 'Network error occurred',
|
|
200
|
-
event: e.type
|
|
201
|
-
}
|
|
210
|
+
event: e.type,
|
|
211
|
+
},
|
|
202
212
|
});
|
|
203
213
|
}
|
|
204
214
|
return handle_error(error_cb, reject_func, this);
|
|
205
|
-
})
|
|
215
|
+
});
|
|
206
216
|
}
|
|
207
217
|
|
|
208
|
-
const NOOP = () => {
|
|
218
|
+
const NOOP = () => {
|
|
219
|
+
};
|
|
209
220
|
class Valid {
|
|
210
221
|
static callback (cb) {
|
|
211
222
|
return (cb && typeof cb === 'function') ? cb : undefined;
|
|
@@ -219,13 +230,13 @@ class Valid {
|
|
|
219
230
|
* @param {string} driverName - name of the driver
|
|
220
231
|
* @param {string} driverMethod - name of the method
|
|
221
232
|
*/
|
|
222
|
-
function make_driver_method(arg_defs, driverInterface, driverName, driverMethod, settings = {}) {
|
|
233
|
+
function make_driver_method (arg_defs, driverInterface, driverName, driverMethod, settings = {}) {
|
|
223
234
|
return async function (...args) {
|
|
224
235
|
let driverArgs = {};
|
|
225
236
|
let options = {};
|
|
226
237
|
|
|
227
238
|
// Check if the first argument is an object and use it as named parameters
|
|
228
|
-
if (args.length === 1 && typeof args[0] === 'object' && !Array.isArray(args[0])) {
|
|
239
|
+
if ( args.length === 1 && typeof args[0] === 'object' && !Array.isArray(args[0]) ) {
|
|
229
240
|
driverArgs = { ...args[0] };
|
|
230
241
|
options = {
|
|
231
242
|
success: driverArgs.success,
|
|
@@ -246,7 +257,7 @@ function make_driver_method(arg_defs, driverInterface, driverName, driverMethod,
|
|
|
246
257
|
}
|
|
247
258
|
|
|
248
259
|
// preprocess
|
|
249
|
-
if(settings.preprocess && typeof settings.preprocess === 'function'){
|
|
260
|
+
if ( settings.preprocess && typeof settings.preprocess === 'function' ) {
|
|
250
261
|
driverArgs = settings.preprocess(driverArgs);
|
|
251
262
|
}
|
|
252
263
|
|
|
@@ -257,24 +268,22 @@ function make_driver_method(arg_defs, driverInterface, driverName, driverMethod,
|
|
|
257
268
|
async function driverCall (options, driverInterface, driverName, driverMethod, driverArgs, settings) {
|
|
258
269
|
const tp = new TeePromise();
|
|
259
270
|
|
|
260
|
-
driverCall_(
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
settings,
|
|
271
|
-
);
|
|
271
|
+
driverCall_(options,
|
|
272
|
+
tp.resolve.bind(tp),
|
|
273
|
+
tp.reject.bind(tp),
|
|
274
|
+
driverInterface,
|
|
275
|
+
driverName,
|
|
276
|
+
driverMethod,
|
|
277
|
+
driverArgs,
|
|
278
|
+
undefined,
|
|
279
|
+
undefined,
|
|
280
|
+
settings);
|
|
272
281
|
|
|
273
282
|
return await tp;
|
|
274
283
|
}
|
|
275
284
|
|
|
276
285
|
// This function encapsulates the logic for sending a driver call request
|
|
277
|
-
async function driverCall_(
|
|
286
|
+
async function driverCall_ (
|
|
278
287
|
options = {},
|
|
279
288
|
resolve_func, reject_func,
|
|
280
289
|
driverInterface, driverName, driverMethod, driverArgs,
|
|
@@ -285,34 +294,34 @@ async function driverCall_(
|
|
|
285
294
|
// Generate request ID for logging
|
|
286
295
|
// Store request info for logging
|
|
287
296
|
let requestInfo = null;
|
|
288
|
-
if (globalThis.puter?.apiCallLogger?.isEnabled()) {
|
|
297
|
+
if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
|
|
289
298
|
requestInfo = {
|
|
290
299
|
interface: driverInterface,
|
|
291
300
|
driver: driverName,
|
|
292
301
|
method: driverMethod,
|
|
293
|
-
args: driverArgs
|
|
302
|
+
args: driverArgs,
|
|
294
303
|
};
|
|
295
304
|
}
|
|
296
305
|
|
|
297
306
|
// If there is no authToken and the environment is web, try authenticating with Puter
|
|
298
|
-
if(!puter.authToken && puter.env === 'web'){
|
|
299
|
-
try{
|
|
307
|
+
if ( !puter.authToken && puter.env === 'web' ) {
|
|
308
|
+
try {
|
|
300
309
|
await puter.ui.authenticateWithPuter();
|
|
301
|
-
}catch(e){
|
|
310
|
+
} catch (e) {
|
|
302
311
|
// Log authentication error
|
|
303
|
-
if (requestInfo && globalThis.puter?.apiCallLogger?.isEnabled()) {
|
|
312
|
+
if ( requestInfo && globalThis.puter?.apiCallLogger?.isEnabled() ) {
|
|
304
313
|
globalThis.puter.apiCallLogger.logRequest({
|
|
305
314
|
service: 'drivers',
|
|
306
315
|
operation: `${driverInterface}::${driverMethod}`,
|
|
307
316
|
params: { interface: driverInterface, driver: driverName, method: driverMethod, args: driverArgs },
|
|
308
|
-
error: { code: 'auth_canceled', message: 'Authentication canceled' }
|
|
317
|
+
error: { code: 'auth_canceled', message: 'Authentication canceled' },
|
|
309
318
|
});
|
|
310
319
|
}
|
|
311
320
|
return reject_func({
|
|
312
321
|
error: {
|
|
313
|
-
code: 'auth_canceled', message: 'Authentication canceled'
|
|
314
|
-
}
|
|
315
|
-
})
|
|
322
|
+
code: 'auth_canceled', message: 'Authentication canceled',
|
|
323
|
+
},
|
|
324
|
+
});
|
|
316
325
|
}
|
|
317
326
|
}
|
|
318
327
|
|
|
@@ -322,14 +331,14 @@ async function driverCall_(
|
|
|
322
331
|
const xhr = initXhr('/drivers/call', puter.APIOrigin, undefined, 'POST', contentType);
|
|
323
332
|
|
|
324
333
|
// Store request info for later logging
|
|
325
|
-
if (requestInfo) {
|
|
334
|
+
if ( requestInfo ) {
|
|
326
335
|
xhr._puterDriverRequestInfo = requestInfo;
|
|
327
336
|
}
|
|
328
337
|
|
|
329
338
|
if ( settings.responseType ) {
|
|
330
339
|
xhr.responseType = settings.responseType;
|
|
331
340
|
}
|
|
332
|
-
|
|
341
|
+
|
|
333
342
|
// ===============================================
|
|
334
343
|
// TO UNDERSTAND THIS CODE, YOU MUST FIRST
|
|
335
344
|
// UNDERSTAND THE FOLLOWING TEXT:
|
|
@@ -338,14 +347,14 @@ async function driverCall_(
|
|
|
338
347
|
// "=== END OF STREAMING ===" is ONLY for handling
|
|
339
348
|
// requests with content type "application/x-ndjson"
|
|
340
349
|
// ===============================================
|
|
341
|
-
|
|
350
|
+
|
|
342
351
|
let is_stream = false;
|
|
343
352
|
let signal_stream_update = null;
|
|
344
353
|
let lastLength = 0;
|
|
345
354
|
let response_complete = false;
|
|
346
|
-
|
|
355
|
+
|
|
347
356
|
let buffer = '';
|
|
348
|
-
|
|
357
|
+
|
|
349
358
|
// NOTE: linked-list technically would perform better,
|
|
350
359
|
// but in practice there are at most 2-3 lines
|
|
351
360
|
// buffered so this does not matter.
|
|
@@ -353,12 +362,12 @@ async function driverCall_(
|
|
|
353
362
|
|
|
354
363
|
xhr.onreadystatechange = () => {
|
|
355
364
|
if ( xhr.readyState === 2 ) {
|
|
356
|
-
if ( xhr.getResponseHeader(
|
|
365
|
+
if ( xhr.getResponseHeader('Content-Type') !==
|
|
357
366
|
'application/x-ndjson'
|
|
358
367
|
) return;
|
|
359
368
|
is_stream = true;
|
|
360
369
|
const Stream = async function* Stream () {
|
|
361
|
-
while ( !
|
|
370
|
+
while ( !response_complete ) {
|
|
362
371
|
const tp = new TeePromise();
|
|
363
372
|
signal_stream_update = tp.resolve.bind(tp);
|
|
364
373
|
await tp;
|
|
@@ -367,7 +376,7 @@ async function driverCall_(
|
|
|
367
376
|
const line = lines_received.shift();
|
|
368
377
|
if ( line.trim() === '' ) continue;
|
|
369
378
|
const lineObject = (JSON.parse(line));
|
|
370
|
-
if (typeof (lineObject.text) === 'string') {
|
|
379
|
+
if ( typeof (lineObject.text) === 'string' ) {
|
|
371
380
|
Object.defineProperty(lineObject, 'toString', {
|
|
372
381
|
enumerable: false,
|
|
373
382
|
value: () => lineObject.text,
|
|
@@ -376,20 +385,20 @@ async function driverCall_(
|
|
|
376
385
|
yield lineObject;
|
|
377
386
|
}
|
|
378
387
|
}
|
|
379
|
-
}
|
|
388
|
+
};
|
|
380
389
|
|
|
381
390
|
const startedStream = Stream();
|
|
382
391
|
Object.defineProperty(startedStream, 'start', {
|
|
383
392
|
enumerable: false,
|
|
384
|
-
value: async(controller) => {
|
|
393
|
+
value: async (controller) => {
|
|
385
394
|
const texten = new TextEncoder();
|
|
386
|
-
for await (const part of startedStream) {
|
|
387
|
-
controller.enqueue(texten.encode(part))
|
|
395
|
+
for await ( const part of startedStream ) {
|
|
396
|
+
controller.enqueue(texten.encode(part));
|
|
388
397
|
}
|
|
389
398
|
controller.close();
|
|
390
|
-
}
|
|
391
|
-
})
|
|
392
|
-
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
|
|
393
402
|
return resolve_func(startedStream);
|
|
394
403
|
}
|
|
395
404
|
if ( xhr.readyState === 4 ) {
|
|
@@ -400,12 +409,12 @@ async function driverCall_(
|
|
|
400
409
|
}
|
|
401
410
|
};
|
|
402
411
|
|
|
403
|
-
xhr.onprogress = function() {
|
|
412
|
+
xhr.onprogress = function () {
|
|
404
413
|
if ( ! signal_stream_update ) return;
|
|
405
414
|
|
|
406
415
|
const newText = xhr.responseText.slice(lastLength);
|
|
407
416
|
lastLength = xhr.responseText.length; // Update lastLength to the current length
|
|
408
|
-
|
|
417
|
+
|
|
409
418
|
let hasUpdates = false;
|
|
410
419
|
for ( let i = 0; i < newText.length; i++ ) {
|
|
411
420
|
buffer += newText[i];
|
|
@@ -415,83 +424,85 @@ async function driverCall_(
|
|
|
415
424
|
buffer = '';
|
|
416
425
|
}
|
|
417
426
|
}
|
|
418
|
-
|
|
427
|
+
|
|
419
428
|
if ( hasUpdates ) {
|
|
420
429
|
signal_stream_update();
|
|
421
430
|
}
|
|
422
431
|
};
|
|
423
|
-
|
|
432
|
+
|
|
424
433
|
// ========================
|
|
425
434
|
// === END OF STREAMING ===
|
|
426
435
|
// ========================
|
|
427
436
|
|
|
428
437
|
// load: success or error
|
|
429
|
-
xhr.addEventListener('load', async function(response){
|
|
438
|
+
xhr.addEventListener('load', async function (response) {
|
|
430
439
|
if ( is_stream ) {
|
|
431
440
|
return;
|
|
432
441
|
}
|
|
433
442
|
const resp = await parseResponse(response.target);
|
|
434
|
-
|
|
443
|
+
|
|
435
444
|
// Log driver call response
|
|
436
|
-
if (this._puterDriverRequestInfo && globalThis.puter?.apiCallLogger?.isEnabled()) {
|
|
445
|
+
if ( this._puterDriverRequestInfo && globalThis.puter?.apiCallLogger?.isEnabled() ) {
|
|
437
446
|
globalThis.puter.apiCallLogger.logRequest({
|
|
438
447
|
service: 'drivers',
|
|
439
448
|
operation: `${this._puterDriverRequestInfo.interface}::${this._puterDriverRequestInfo.method}`,
|
|
440
449
|
params: { interface: this._puterDriverRequestInfo.interface, driver: this._puterDriverRequestInfo.driver, method: this._puterDriverRequestInfo.method, args: this._puterDriverRequestInfo.args },
|
|
441
450
|
result: response.status >= 400 || resp?.success === false ? null : resp,
|
|
442
|
-
error: response.status >= 400 || resp?.success === false ? resp : null
|
|
451
|
+
error: response.status >= 400 || resp?.success === false ? resp : null,
|
|
443
452
|
});
|
|
444
453
|
}
|
|
445
|
-
|
|
454
|
+
|
|
446
455
|
// HTTP Error - unauthorized
|
|
447
|
-
if(response.status === 401 || resp?.code ===
|
|
448
|
-
if(resp?.code ===
|
|
449
|
-
try{
|
|
456
|
+
if ( response.status === 401 || resp?.code === 'token_auth_failed' ) {
|
|
457
|
+
if ( resp?.code === 'token_auth_failed' && puter.env === 'web' ) {
|
|
458
|
+
try {
|
|
450
459
|
puter.resetAuthToken();
|
|
451
460
|
await puter.ui.authenticateWithPuter();
|
|
452
|
-
}catch(e){
|
|
461
|
+
} catch (e) {
|
|
453
462
|
return reject_func({
|
|
454
463
|
error: {
|
|
455
|
-
code: 'auth_canceled', message: 'Authentication canceled'
|
|
456
|
-
}
|
|
457
|
-
})
|
|
464
|
+
code: 'auth_canceled', message: 'Authentication canceled',
|
|
465
|
+
},
|
|
466
|
+
});
|
|
458
467
|
}
|
|
459
468
|
}
|
|
460
469
|
// if error callback is provided, call it
|
|
461
|
-
if(error_cb && typeof error_cb === 'function')
|
|
462
|
-
|
|
470
|
+
if ( error_cb && typeof error_cb === 'function' )
|
|
471
|
+
{
|
|
472
|
+
error_cb({ status: 401, message: 'Unauthorized' });
|
|
473
|
+
}
|
|
463
474
|
// reject promise
|
|
464
|
-
return reject_func({status: 401, message: 'Unauthorized'})
|
|
475
|
+
return reject_func({ status: 401, message: 'Unauthorized' });
|
|
465
476
|
}
|
|
466
477
|
// HTTP Error - other
|
|
467
|
-
else if(response.status && response.status !== 200){
|
|
478
|
+
else if ( response.status && response.status !== 200 ) {
|
|
468
479
|
// if error callback is provided, call it
|
|
469
|
-
error_cb(resp)
|
|
480
|
+
error_cb(resp);
|
|
470
481
|
// reject promise
|
|
471
|
-
return reject_func(resp)
|
|
482
|
+
return reject_func(resp);
|
|
472
483
|
}
|
|
473
484
|
// HTTP Success
|
|
474
|
-
else{
|
|
485
|
+
else {
|
|
475
486
|
// Driver Error: permission denied
|
|
476
|
-
if(resp.success === false && resp.error?.code === 'permission_denied'){
|
|
477
|
-
let perm = await puter.ui.requestPermission({permission:
|
|
487
|
+
if ( resp.success === false && resp.error?.code === 'permission_denied' ) {
|
|
488
|
+
let perm = await puter.ui.requestPermission({ permission: `driver:${ driverInterface }:${ driverMethod}` });
|
|
478
489
|
// try sending again if permission was granted
|
|
479
|
-
if(perm.granted){
|
|
490
|
+
if ( perm.granted ) {
|
|
480
491
|
// repeat request with permission granted
|
|
481
492
|
return driverCall_(options, resolve_func, reject_func, driverInterface, driverMethod, driverArgs, method, contentType, settings);
|
|
482
|
-
}else{
|
|
493
|
+
} else {
|
|
483
494
|
// if error callback is provided, call it
|
|
484
|
-
error_cb(resp)
|
|
495
|
+
error_cb(resp);
|
|
485
496
|
// reject promise
|
|
486
|
-
return reject_func(resp)
|
|
497
|
+
return reject_func(resp);
|
|
487
498
|
}
|
|
488
499
|
}
|
|
489
500
|
// Driver Error: other
|
|
490
|
-
else if(resp.success === false){
|
|
501
|
+
else if ( resp.success === false ) {
|
|
491
502
|
// if error callback is provided, call it
|
|
492
|
-
error_cb(resp)
|
|
503
|
+
error_cb(resp);
|
|
493
504
|
// reject promise
|
|
494
|
-
return reject_func(resp)
|
|
505
|
+
return reject_func(resp);
|
|
495
506
|
}
|
|
496
507
|
|
|
497
508
|
let result = resp.result !== undefined ? resp.result : resp;
|
|
@@ -500,35 +511,37 @@ async function driverCall_(
|
|
|
500
511
|
}
|
|
501
512
|
|
|
502
513
|
// Success: if callback is provided, call it
|
|
503
|
-
if(resolve_func.success)
|
|
514
|
+
if ( resolve_func.success )
|
|
515
|
+
{
|
|
504
516
|
success_cb(result);
|
|
517
|
+
}
|
|
505
518
|
// Success: resolve with the result
|
|
506
519
|
return resolve_func(result);
|
|
507
520
|
}
|
|
508
521
|
});
|
|
509
522
|
|
|
510
523
|
// error
|
|
511
|
-
xhr.addEventListener('error', function(e){
|
|
524
|
+
xhr.addEventListener('error', function (e) {
|
|
512
525
|
// Log driver call error
|
|
513
|
-
if (this._puterDriverRequestInfo && globalThis.puter?.apiCallLogger?.isEnabled()) {
|
|
526
|
+
if ( this._puterDriverRequestInfo && globalThis.puter?.apiCallLogger?.isEnabled() ) {
|
|
514
527
|
globalThis.puter.apiCallLogger.logRequest({
|
|
515
528
|
service: 'drivers',
|
|
516
529
|
operation: `${this._puterDriverRequestInfo.interface}::${this._puterDriverRequestInfo.method}`,
|
|
517
530
|
params: { interface: this._puterDriverRequestInfo.interface, driver: this._puterDriverRequestInfo.driver, method: this._puterDriverRequestInfo.method, args: this._puterDriverRequestInfo.args },
|
|
518
|
-
error: { message: 'Network error occurred', event: e.type }
|
|
531
|
+
error: { message: 'Network error occurred', event: e.type },
|
|
519
532
|
});
|
|
520
533
|
}
|
|
521
534
|
return handle_error(error_cb, reject_func, this);
|
|
522
|
-
})
|
|
535
|
+
});
|
|
523
536
|
|
|
524
537
|
// send request
|
|
525
538
|
xhr.send(JSON.stringify({
|
|
526
539
|
interface: driverInterface,
|
|
527
540
|
driver: driverName,
|
|
528
|
-
test_mode: settings?.test_mode,
|
|
541
|
+
test_mode: settings?.test_mode,
|
|
529
542
|
method: driverMethod,
|
|
530
543
|
args: driverArgs,
|
|
531
|
-
auth_token: puter.authToken
|
|
544
|
+
auth_token: puter.authToken,
|
|
532
545
|
}));
|
|
533
546
|
}
|
|
534
547
|
|
|
@@ -567,54 +580,50 @@ class TeePromise {
|
|
|
567
580
|
this.status_ = this.constructor.STATUS_DONE;
|
|
568
581
|
this.doneReject(err);
|
|
569
582
|
}
|
|
570
|
-
|
|
583
|
+
|
|
571
584
|
/**
|
|
572
585
|
* @deprecated use then() instead
|
|
573
586
|
*/
|
|
574
|
-
onComplete(fn) {
|
|
587
|
+
onComplete (fn) {
|
|
575
588
|
return this.then(fn);
|
|
576
589
|
}
|
|
577
590
|
}
|
|
578
591
|
|
|
579
592
|
async function blob_to_url (blob) {
|
|
580
593
|
const tp = new TeePromise();
|
|
581
|
-
const reader = new FileReader();
|
|
594
|
+
const reader = new (globalThis.FileReader || FileReaderPoly)();
|
|
582
595
|
reader.onloadend = () => tp.resolve(reader.result);
|
|
583
596
|
reader.readAsDataURL(blob);
|
|
584
597
|
return await tp;
|
|
585
598
|
}
|
|
586
599
|
|
|
587
|
-
function blobToDataUri(blob) {
|
|
600
|
+
function blobToDataUri (blob) {
|
|
588
601
|
return new Promise((resolve, reject) => {
|
|
589
|
-
const reader = new FileReader();
|
|
590
|
-
reader.onload = function(event) {
|
|
602
|
+
const reader = new (globalThis.FileReader || FileReaderPoly)();
|
|
603
|
+
reader.onload = function (event) {
|
|
591
604
|
resolve(event.target.result);
|
|
592
605
|
};
|
|
593
|
-
reader.onerror = function(error) {
|
|
606
|
+
reader.onerror = function (error) {
|
|
594
607
|
reject(error);
|
|
595
608
|
};
|
|
596
609
|
reader.readAsDataURL(blob);
|
|
597
610
|
});
|
|
598
611
|
}
|
|
599
612
|
|
|
600
|
-
function arrayBufferToDataUri(arrayBuffer) {
|
|
613
|
+
function arrayBufferToDataUri (arrayBuffer) {
|
|
601
614
|
return new Promise((resolve, reject) => {
|
|
602
615
|
const blob = new Blob([arrayBuffer]);
|
|
603
|
-
const reader = new FileReader();
|
|
604
|
-
reader.onload = function(event) {
|
|
616
|
+
const reader = new (globalThis.FileReader || FileReaderPoly)();
|
|
617
|
+
reader.onload = function (event) {
|
|
605
618
|
resolve(event.target.result);
|
|
606
619
|
};
|
|
607
|
-
reader.onerror = function(error) {
|
|
620
|
+
reader.onerror = function (error) {
|
|
608
621
|
reject(error);
|
|
609
622
|
};
|
|
610
623
|
reader.readAsDataURL(blob);
|
|
611
624
|
});
|
|
612
625
|
}
|
|
613
626
|
|
|
614
|
-
export {
|
|
615
|
-
TeePromise,
|
|
616
|
-
|
|
617
|
-
blob_to_url,
|
|
618
|
-
arrayBufferToDataUri,
|
|
619
|
-
blobToDataUri,
|
|
620
|
-
};
|
|
627
|
+
export {
|
|
628
|
+
arrayBufferToDataUri, blob_to_url, blobToDataUri, driverCall, handle_error, handle_resp, initXhr, make_driver_method, parseResponse, setupXhrEventHandlers, TeePromise, uuidv4
|
|
629
|
+
};
|