@drawbridge/drawbridge-utils 0.0.99 → 0.0.101
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/ai.cjs +10 -0
- package/dist/ai.js +10 -0
- package/dist/billing.cjs +10 -0
- package/dist/billing.d.cts +10 -0
- package/dist/billing.d.ts +10 -0
- package/dist/billing.js +10 -0
- package/dist/features.cjs +1 -1
- package/dist/features.d.cts +1 -1
- package/dist/features.d.ts +1 -1
- package/dist/features.js +1 -1
- package/dist/fetch.cjs +2 -57
- package/dist/fetch.d.cts +1 -113
- package/dist/fetch.d.ts +1 -113
- package/dist/fetch.js +1 -55
- package/dist/plans.cjs +1 -1
- package/dist/plans.js +1 -1
- package/dist/upload.cjs +2 -27
- package/dist/upload.d.cts +1 -59
- package/dist/upload.d.ts +1 -59
- package/dist/upload.js +1 -23
- package/package.json +1 -1
package/dist/ai.cjs
CHANGED
|
@@ -168,6 +168,16 @@ var cost = {
|
|
|
168
168
|
input: 150,
|
|
169
169
|
output: 900
|
|
170
170
|
},
|
|
171
|
+
// gemini-3.5-flash-lite — verified against Google's pricing page 2026-08-20:
|
|
172
|
+
// $0.03 cached / $0.30 input / $2.50 output per 1M tokens (thinking billed at
|
|
173
|
+
// output). A fifth of flash on input, ~a quarter on output. Growth's assistant
|
|
174
|
+
// ranks the feed on this tier — one call per page — so its rows were the
|
|
175
|
+
// unpriced ones until now.
|
|
176
|
+
"gemini-3.5-flash-lite": {
|
|
177
|
+
cached: 3,
|
|
178
|
+
input: 30,
|
|
179
|
+
output: 250
|
|
180
|
+
},
|
|
171
181
|
"gemini-2.5-flash": {
|
|
172
182
|
cached: 3,
|
|
173
183
|
input: 30,
|
package/dist/ai.js
CHANGED
|
@@ -134,6 +134,16 @@ var cost = {
|
|
|
134
134
|
input: 150,
|
|
135
135
|
output: 900
|
|
136
136
|
},
|
|
137
|
+
// gemini-3.5-flash-lite — verified against Google's pricing page 2026-08-20:
|
|
138
|
+
// $0.03 cached / $0.30 input / $2.50 output per 1M tokens (thinking billed at
|
|
139
|
+
// output). A fifth of flash on input, ~a quarter on output. Growth's assistant
|
|
140
|
+
// ranks the feed on this tier — one call per page — so its rows were the
|
|
141
|
+
// unpriced ones until now.
|
|
142
|
+
"gemini-3.5-flash-lite": {
|
|
143
|
+
cached: 3,
|
|
144
|
+
input: 30,
|
|
145
|
+
output: 250
|
|
146
|
+
},
|
|
137
147
|
"gemini-2.5-flash": {
|
|
138
148
|
cached: 3,
|
|
139
149
|
input: 30,
|
package/dist/billing.cjs
CHANGED
|
@@ -168,6 +168,16 @@ var cost = {
|
|
|
168
168
|
input: 150,
|
|
169
169
|
output: 900
|
|
170
170
|
},
|
|
171
|
+
// gemini-3.5-flash-lite — verified against Google's pricing page 2026-08-20:
|
|
172
|
+
// $0.03 cached / $0.30 input / $2.50 output per 1M tokens (thinking billed at
|
|
173
|
+
// output). A fifth of flash on input, ~a quarter on output. Growth's assistant
|
|
174
|
+
// ranks the feed on this tier — one call per page — so its rows were the
|
|
175
|
+
// unpriced ones until now.
|
|
176
|
+
"gemini-3.5-flash-lite": {
|
|
177
|
+
cached: 3,
|
|
178
|
+
input: 30,
|
|
179
|
+
output: 250
|
|
180
|
+
},
|
|
171
181
|
"gemini-2.5-flash": {
|
|
172
182
|
cached: 3,
|
|
173
183
|
input: 30,
|
package/dist/billing.d.cts
CHANGED
|
@@ -39,6 +39,16 @@ const cost = {
|
|
|
39
39
|
input : 150,
|
|
40
40
|
output : 900
|
|
41
41
|
},
|
|
42
|
+
// gemini-3.5-flash-lite — verified against Google's pricing page 2026-08-20:
|
|
43
|
+
// $0.03 cached / $0.30 input / $2.50 output per 1M tokens (thinking billed at
|
|
44
|
+
// output). A fifth of flash on input, ~a quarter on output. Growth's assistant
|
|
45
|
+
// ranks the feed on this tier — one call per page — so its rows were the
|
|
46
|
+
// unpriced ones until now.
|
|
47
|
+
'gemini-3.5-flash-lite' : {
|
|
48
|
+
cached : 3,
|
|
49
|
+
input : 30,
|
|
50
|
+
output : 250
|
|
51
|
+
},
|
|
42
52
|
'gemini-2.5-flash' : {
|
|
43
53
|
cached : 3,
|
|
44
54
|
input : 30,
|
package/dist/billing.d.ts
CHANGED
|
@@ -39,6 +39,16 @@ const cost = {
|
|
|
39
39
|
input : 150,
|
|
40
40
|
output : 900
|
|
41
41
|
},
|
|
42
|
+
// gemini-3.5-flash-lite — verified against Google's pricing page 2026-08-20:
|
|
43
|
+
// $0.03 cached / $0.30 input / $2.50 output per 1M tokens (thinking billed at
|
|
44
|
+
// output). A fifth of flash on input, ~a quarter on output. Growth's assistant
|
|
45
|
+
// ranks the feed on this tier — one call per page — so its rows were the
|
|
46
|
+
// unpriced ones until now.
|
|
47
|
+
'gemini-3.5-flash-lite' : {
|
|
48
|
+
cached : 3,
|
|
49
|
+
input : 30,
|
|
50
|
+
output : 250
|
|
51
|
+
},
|
|
42
52
|
'gemini-2.5-flash' : {
|
|
43
53
|
cached : 3,
|
|
44
54
|
input : 30,
|
package/dist/billing.js
CHANGED
|
@@ -138,6 +138,16 @@ var cost = {
|
|
|
138
138
|
input: 150,
|
|
139
139
|
output: 900
|
|
140
140
|
},
|
|
141
|
+
// gemini-3.5-flash-lite — verified against Google's pricing page 2026-08-20:
|
|
142
|
+
// $0.03 cached / $0.30 input / $2.50 output per 1M tokens (thinking billed at
|
|
143
|
+
// output). A fifth of flash on input, ~a quarter on output. Growth's assistant
|
|
144
|
+
// ranks the feed on this tier — one call per page — so its rows were the
|
|
145
|
+
// unpriced ones until now.
|
|
146
|
+
"gemini-3.5-flash-lite": {
|
|
147
|
+
cached: 3,
|
|
148
|
+
input: 30,
|
|
149
|
+
output: 250
|
|
150
|
+
},
|
|
141
151
|
"gemini-2.5-flash": {
|
|
142
152
|
cached: 3,
|
|
143
153
|
input: 30,
|
package/dist/features.cjs
CHANGED
package/dist/features.d.cts
CHANGED
package/dist/features.d.ts
CHANGED
package/dist/features.js
CHANGED
package/dist/fetch.cjs
CHANGED
|
@@ -32,8 +32,7 @@ __export(fetch_exports, {
|
|
|
32
32
|
isTransientError: () => isTransientError,
|
|
33
33
|
queryString: () => queryString,
|
|
34
34
|
request: () => request,
|
|
35
|
-
setMemoryToken: () => setMemoryToken
|
|
36
|
-
upload: () => upload
|
|
35
|
+
setMemoryToken: () => setMemoryToken
|
|
37
36
|
});
|
|
38
37
|
module.exports = __toCommonJS(fetch_exports);
|
|
39
38
|
var import_qs = __toESM(require("qs"), 1);
|
|
@@ -123,59 +122,6 @@ var request = async ({
|
|
|
123
122
|
}
|
|
124
123
|
return res;
|
|
125
124
|
};
|
|
126
|
-
var upload = ({
|
|
127
|
-
body,
|
|
128
|
-
endpoint,
|
|
129
|
-
method = "POST",
|
|
130
|
-
onProgress,
|
|
131
|
-
signal,
|
|
132
|
-
token,
|
|
133
|
-
url = process.env.NEXT_PUBLIC_API_URI
|
|
134
|
-
}) => {
|
|
135
|
-
const authToken = token || (typeof window !== "undefined" ? memoryToken : null);
|
|
136
|
-
const csrf = readCsrf();
|
|
137
|
-
return new Promise((resolve, reject) => {
|
|
138
|
-
const xhr = new XMLHttpRequest();
|
|
139
|
-
xhr.open(method, url + endpoint, true);
|
|
140
|
-
xhr.setRequestHeader("accept", "application/json");
|
|
141
|
-
if (authToken) {
|
|
142
|
-
xhr.setRequestHeader("authorization", "Bearer " + authToken);
|
|
143
|
-
}
|
|
144
|
-
if (csrf) {
|
|
145
|
-
xhr.setRequestHeader("x-drawbridge-csrf", csrf);
|
|
146
|
-
}
|
|
147
|
-
xhr.upload.addEventListener("progress", (event) => {
|
|
148
|
-
if (!event.lengthComputable || !onProgress) return;
|
|
149
|
-
onProgress({
|
|
150
|
-
bytesTotal: event.total,
|
|
151
|
-
bytesUploaded: event.loaded
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
xhr.addEventListener("load", () => {
|
|
155
|
-
let data = null;
|
|
156
|
-
try {
|
|
157
|
-
data = JSON.parse(xhr.responseText);
|
|
158
|
-
} catch {
|
|
159
|
-
data = null;
|
|
160
|
-
}
|
|
161
|
-
if (xhr.status >= 200 && xhr.status < 300) return resolve(data);
|
|
162
|
-
const error = new Error((data == null ? void 0 : data.message) || xhr.statusText);
|
|
163
|
-
error.status = xhr.status;
|
|
164
|
-
error.data = data;
|
|
165
|
-
reject(error);
|
|
166
|
-
});
|
|
167
|
-
xhr.addEventListener("abort", () => {
|
|
168
|
-
const error = new Error("Upload cancelled");
|
|
169
|
-
error.name = "AbortError";
|
|
170
|
-
reject(error);
|
|
171
|
-
});
|
|
172
|
-
xhr.addEventListener("error", () => reject(new Error("Network error")));
|
|
173
|
-
if (signal) {
|
|
174
|
-
signal.addEventListener("abort", () => xhr.abort(), { once: true });
|
|
175
|
-
}
|
|
176
|
-
xhr.send(body);
|
|
177
|
-
});
|
|
178
|
-
};
|
|
179
125
|
var isTransientError = (error) => {
|
|
180
126
|
const status = error == null ? void 0 : error.status;
|
|
181
127
|
return !status || status === 429 || status >= 500;
|
|
@@ -185,6 +131,5 @@ var isTransientError = (error) => {
|
|
|
185
131
|
isTransientError,
|
|
186
132
|
queryString,
|
|
187
133
|
request,
|
|
188
|
-
setMemoryToken
|
|
189
|
-
upload
|
|
134
|
+
setMemoryToken
|
|
190
135
|
});
|
package/dist/fetch.d.cts
CHANGED
|
@@ -124,118 +124,6 @@ const request = async ({
|
|
|
124
124
|
|
|
125
125
|
};
|
|
126
126
|
|
|
127
|
-
// fetch() has no upload-progress event and never will, which is the reason every
|
|
128
|
-
// upload in the dashboard could only ever show a spinner. XHR does, so anything
|
|
129
|
-
// that wants a real progress bar posts through here instead.
|
|
130
|
-
//
|
|
131
|
-
// It lives beside request() rather than in the dashboard because `memoryToken`
|
|
132
|
-
// above is module-private on purpose — a copy in app-web could only read it if
|
|
133
|
-
// the token were exported, which is the one thing setMemoryToken exists to
|
|
134
|
-
// prevent. The csrf cookie read is here too.
|
|
135
|
-
//
|
|
136
|
-
// The error shape is deliberately identical to request()'s — an Error carrying
|
|
137
|
-
// .status and .data — so isTransientError() and every existing catch block work
|
|
138
|
-
// against either transport without knowing which ran.
|
|
139
|
-
const upload = ({
|
|
140
|
-
body,
|
|
141
|
-
endpoint,
|
|
142
|
-
method = 'POST',
|
|
143
|
-
onProgress,
|
|
144
|
-
signal,
|
|
145
|
-
token,
|
|
146
|
-
url = process.env.NEXT_PUBLIC_API_URI
|
|
147
|
-
}) => {
|
|
148
|
-
|
|
149
|
-
const authToken = token || ( typeof window !== 'undefined' ? memoryToken : null );
|
|
150
|
-
const csrf = readCsrf();
|
|
151
|
-
|
|
152
|
-
return new Promise( ( resolve, reject ) => {
|
|
153
|
-
|
|
154
|
-
const xhr = new XMLHttpRequest();
|
|
155
|
-
|
|
156
|
-
xhr.open( method, url + endpoint, true );
|
|
157
|
-
|
|
158
|
-
// No content-type, ever. The browser has to write the multipart boundary
|
|
159
|
-
// itself and setting the header by hand drops it, which busboy then
|
|
160
|
-
// rejects. Nor origin: it is a forbidden header name, so the browser
|
|
161
|
-
// ignores setRequestHeader for it ( request() only sets it because its
|
|
162
|
-
// server-side callers run where fetch allows it ).
|
|
163
|
-
xhr.setRequestHeader( 'accept', 'application/json' );
|
|
164
|
-
|
|
165
|
-
if( authToken ){
|
|
166
|
-
|
|
167
|
-
xhr.setRequestHeader( 'authorization', 'Bearer ' + authToken );
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if( csrf ){
|
|
172
|
-
|
|
173
|
-
xhr.setRequestHeader( 'x-drawbridge-csrf', csrf );
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
xhr.upload.addEventListener( 'progress', ( event ) => {
|
|
178
|
-
|
|
179
|
-
if( ! event.lengthComputable || ! onProgress ) return;
|
|
180
|
-
|
|
181
|
-
onProgress({
|
|
182
|
-
bytesTotal : event.total,
|
|
183
|
-
bytesUploaded : event.loaded
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
xhr.addEventListener( 'load', () => {
|
|
189
|
-
|
|
190
|
-
let data = null;
|
|
191
|
-
|
|
192
|
-
try {
|
|
193
|
-
|
|
194
|
-
data = JSON.parse( xhr.responseText );
|
|
195
|
-
|
|
196
|
-
} catch {
|
|
197
|
-
|
|
198
|
-
data = null;
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if( xhr.status >= 200 && xhr.status < 300 ) return resolve( data );
|
|
203
|
-
|
|
204
|
-
const error = new Error( data?.message || xhr.statusText );
|
|
205
|
-
|
|
206
|
-
error.status = xhr.status;
|
|
207
|
-
error.data = data;
|
|
208
|
-
|
|
209
|
-
reject( error );
|
|
210
|
-
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
xhr.addEventListener( 'abort', () => {
|
|
214
|
-
|
|
215
|
-
const error = new Error( 'Upload cancelled' );
|
|
216
|
-
|
|
217
|
-
error.name = 'AbortError';
|
|
218
|
-
|
|
219
|
-
reject( error );
|
|
220
|
-
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
// No status on a network failure, which is exactly how isTransientError
|
|
224
|
-
// classifies it — worth a retry rather than a sign-in bounce.
|
|
225
|
-
xhr.addEventListener( 'error', () => reject( new Error( 'Network error' ) ) );
|
|
226
|
-
|
|
227
|
-
if( signal ){
|
|
228
|
-
|
|
229
|
-
signal.addEventListener( 'abort', () => xhr.abort(), { once : true } );
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
xhr.send( body );
|
|
234
|
-
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
};
|
|
238
|
-
|
|
239
127
|
// Classifies an error thrown by request() — which carries `.status` from the
|
|
240
128
|
// HTTP response, or no status for a network / parse failure. Transient errors
|
|
241
129
|
// ( rate limits, server errors, connection blips ) may succeed on retry, so
|
|
@@ -251,4 +139,4 @@ const isTransientError = ( error ) => {
|
|
|
251
139
|
|
|
252
140
|
};
|
|
253
141
|
|
|
254
|
-
export { isTransientError, queryString, request, setMemoryToken
|
|
142
|
+
export { isTransientError, queryString, request, setMemoryToken };
|
package/dist/fetch.d.ts
CHANGED
|
@@ -124,118 +124,6 @@ const request = async ({
|
|
|
124
124
|
|
|
125
125
|
};
|
|
126
126
|
|
|
127
|
-
// fetch() has no upload-progress event and never will, which is the reason every
|
|
128
|
-
// upload in the dashboard could only ever show a spinner. XHR does, so anything
|
|
129
|
-
// that wants a real progress bar posts through here instead.
|
|
130
|
-
//
|
|
131
|
-
// It lives beside request() rather than in the dashboard because `memoryToken`
|
|
132
|
-
// above is module-private on purpose — a copy in app-web could only read it if
|
|
133
|
-
// the token were exported, which is the one thing setMemoryToken exists to
|
|
134
|
-
// prevent. The csrf cookie read is here too.
|
|
135
|
-
//
|
|
136
|
-
// The error shape is deliberately identical to request()'s — an Error carrying
|
|
137
|
-
// .status and .data — so isTransientError() and every existing catch block work
|
|
138
|
-
// against either transport without knowing which ran.
|
|
139
|
-
const upload = ({
|
|
140
|
-
body,
|
|
141
|
-
endpoint,
|
|
142
|
-
method = 'POST',
|
|
143
|
-
onProgress,
|
|
144
|
-
signal,
|
|
145
|
-
token,
|
|
146
|
-
url = process.env.NEXT_PUBLIC_API_URI
|
|
147
|
-
}) => {
|
|
148
|
-
|
|
149
|
-
const authToken = token || ( typeof window !== 'undefined' ? memoryToken : null );
|
|
150
|
-
const csrf = readCsrf();
|
|
151
|
-
|
|
152
|
-
return new Promise( ( resolve, reject ) => {
|
|
153
|
-
|
|
154
|
-
const xhr = new XMLHttpRequest();
|
|
155
|
-
|
|
156
|
-
xhr.open( method, url + endpoint, true );
|
|
157
|
-
|
|
158
|
-
// No content-type, ever. The browser has to write the multipart boundary
|
|
159
|
-
// itself and setting the header by hand drops it, which busboy then
|
|
160
|
-
// rejects. Nor origin: it is a forbidden header name, so the browser
|
|
161
|
-
// ignores setRequestHeader for it ( request() only sets it because its
|
|
162
|
-
// server-side callers run where fetch allows it ).
|
|
163
|
-
xhr.setRequestHeader( 'accept', 'application/json' );
|
|
164
|
-
|
|
165
|
-
if( authToken ){
|
|
166
|
-
|
|
167
|
-
xhr.setRequestHeader( 'authorization', 'Bearer ' + authToken );
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if( csrf ){
|
|
172
|
-
|
|
173
|
-
xhr.setRequestHeader( 'x-drawbridge-csrf', csrf );
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
xhr.upload.addEventListener( 'progress', ( event ) => {
|
|
178
|
-
|
|
179
|
-
if( ! event.lengthComputable || ! onProgress ) return;
|
|
180
|
-
|
|
181
|
-
onProgress({
|
|
182
|
-
bytesTotal : event.total,
|
|
183
|
-
bytesUploaded : event.loaded
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
xhr.addEventListener( 'load', () => {
|
|
189
|
-
|
|
190
|
-
let data = null;
|
|
191
|
-
|
|
192
|
-
try {
|
|
193
|
-
|
|
194
|
-
data = JSON.parse( xhr.responseText );
|
|
195
|
-
|
|
196
|
-
} catch {
|
|
197
|
-
|
|
198
|
-
data = null;
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if( xhr.status >= 200 && xhr.status < 300 ) return resolve( data );
|
|
203
|
-
|
|
204
|
-
const error = new Error( data?.message || xhr.statusText );
|
|
205
|
-
|
|
206
|
-
error.status = xhr.status;
|
|
207
|
-
error.data = data;
|
|
208
|
-
|
|
209
|
-
reject( error );
|
|
210
|
-
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
xhr.addEventListener( 'abort', () => {
|
|
214
|
-
|
|
215
|
-
const error = new Error( 'Upload cancelled' );
|
|
216
|
-
|
|
217
|
-
error.name = 'AbortError';
|
|
218
|
-
|
|
219
|
-
reject( error );
|
|
220
|
-
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
// No status on a network failure, which is exactly how isTransientError
|
|
224
|
-
// classifies it — worth a retry rather than a sign-in bounce.
|
|
225
|
-
xhr.addEventListener( 'error', () => reject( new Error( 'Network error' ) ) );
|
|
226
|
-
|
|
227
|
-
if( signal ){
|
|
228
|
-
|
|
229
|
-
signal.addEventListener( 'abort', () => xhr.abort(), { once : true } );
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
xhr.send( body );
|
|
234
|
-
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
};
|
|
238
|
-
|
|
239
127
|
// Classifies an error thrown by request() — which carries `.status` from the
|
|
240
128
|
// HTTP response, or no status for a network / parse failure. Transient errors
|
|
241
129
|
// ( rate limits, server errors, connection blips ) may succeed on retry, so
|
|
@@ -251,4 +139,4 @@ const isTransientError = ( error ) => {
|
|
|
251
139
|
|
|
252
140
|
};
|
|
253
141
|
|
|
254
|
-
export { isTransientError, queryString, request, setMemoryToken
|
|
142
|
+
export { isTransientError, queryString, request, setMemoryToken };
|
package/dist/fetch.js
CHANGED
|
@@ -86,59 +86,6 @@ var request = async ({
|
|
|
86
86
|
}
|
|
87
87
|
return res;
|
|
88
88
|
};
|
|
89
|
-
var upload = ({
|
|
90
|
-
body,
|
|
91
|
-
endpoint,
|
|
92
|
-
method = "POST",
|
|
93
|
-
onProgress,
|
|
94
|
-
signal,
|
|
95
|
-
token,
|
|
96
|
-
url = process.env.NEXT_PUBLIC_API_URI
|
|
97
|
-
}) => {
|
|
98
|
-
const authToken = token || (typeof window !== "undefined" ? memoryToken : null);
|
|
99
|
-
const csrf = readCsrf();
|
|
100
|
-
return new Promise((resolve, reject) => {
|
|
101
|
-
const xhr = new XMLHttpRequest();
|
|
102
|
-
xhr.open(method, url + endpoint, true);
|
|
103
|
-
xhr.setRequestHeader("accept", "application/json");
|
|
104
|
-
if (authToken) {
|
|
105
|
-
xhr.setRequestHeader("authorization", "Bearer " + authToken);
|
|
106
|
-
}
|
|
107
|
-
if (csrf) {
|
|
108
|
-
xhr.setRequestHeader("x-drawbridge-csrf", csrf);
|
|
109
|
-
}
|
|
110
|
-
xhr.upload.addEventListener("progress", (event) => {
|
|
111
|
-
if (!event.lengthComputable || !onProgress) return;
|
|
112
|
-
onProgress({
|
|
113
|
-
bytesTotal: event.total,
|
|
114
|
-
bytesUploaded: event.loaded
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
xhr.addEventListener("load", () => {
|
|
118
|
-
let data = null;
|
|
119
|
-
try {
|
|
120
|
-
data = JSON.parse(xhr.responseText);
|
|
121
|
-
} catch {
|
|
122
|
-
data = null;
|
|
123
|
-
}
|
|
124
|
-
if (xhr.status >= 200 && xhr.status < 300) return resolve(data);
|
|
125
|
-
const error = new Error((data == null ? void 0 : data.message) || xhr.statusText);
|
|
126
|
-
error.status = xhr.status;
|
|
127
|
-
error.data = data;
|
|
128
|
-
reject(error);
|
|
129
|
-
});
|
|
130
|
-
xhr.addEventListener("abort", () => {
|
|
131
|
-
const error = new Error("Upload cancelled");
|
|
132
|
-
error.name = "AbortError";
|
|
133
|
-
reject(error);
|
|
134
|
-
});
|
|
135
|
-
xhr.addEventListener("error", () => reject(new Error("Network error")));
|
|
136
|
-
if (signal) {
|
|
137
|
-
signal.addEventListener("abort", () => xhr.abort(), { once: true });
|
|
138
|
-
}
|
|
139
|
-
xhr.send(body);
|
|
140
|
-
});
|
|
141
|
-
};
|
|
142
89
|
var isTransientError = (error) => {
|
|
143
90
|
const status = error == null ? void 0 : error.status;
|
|
144
91
|
return !status || status === 429 || status >= 500;
|
|
@@ -147,6 +94,5 @@ export {
|
|
|
147
94
|
isTransientError,
|
|
148
95
|
queryString,
|
|
149
96
|
request,
|
|
150
|
-
setMemoryToken
|
|
151
|
-
upload
|
|
97
|
+
setMemoryToken
|
|
152
98
|
};
|
package/dist/plans.cjs
CHANGED
package/dist/plans.js
CHANGED
package/dist/upload.cjs
CHANGED
|
@@ -22,10 +22,7 @@ __export(upload_exports, {
|
|
|
22
22
|
allowedMimes: () => allowedMimes,
|
|
23
23
|
allowedUploadTypes: () => allowedUploadTypes,
|
|
24
24
|
isAllowedMime: () => isAllowedMime,
|
|
25
|
-
|
|
26
|
-
resolveUploadType: () => resolveUploadType,
|
|
27
|
-
uploadPartCount: () => uploadPartCount,
|
|
28
|
-
uploadPartSize: () => uploadPartSize
|
|
25
|
+
resolveUploadType: () => resolveUploadType
|
|
29
26
|
});
|
|
30
27
|
module.exports = __toCommonJS(upload_exports);
|
|
31
28
|
var allowedUploadTypes = {
|
|
@@ -39,11 +36,6 @@ var allowedUploadTypes = {
|
|
|
39
36
|
webp: "image/webp"
|
|
40
37
|
},
|
|
41
38
|
video: {
|
|
42
|
-
// iPhones record .mov (HEVC) by default, so this is the single most
|
|
43
|
-
// likely video a merchant uploads. sync's storage.js already computes
|
|
44
|
-
// needsReencode for hevc/h265 and re-encodes to h264, so allowing it
|
|
45
|
-
// here is the only thing the pipeline was waiting on.
|
|
46
|
-
mov: "video/quicktime",
|
|
47
39
|
mp4: "video/mp4"
|
|
48
40
|
}
|
|
49
41
|
};
|
|
@@ -64,27 +56,10 @@ var resolveUploadType = (type, extension) => {
|
|
|
64
56
|
return mime;
|
|
65
57
|
};
|
|
66
58
|
var isAllowedMime = (mime) => allowedMimes.has(mime);
|
|
67
|
-
var megabyte = 1024 * 1024;
|
|
68
|
-
var maximumUploadBytes = 2048 * megabyte;
|
|
69
|
-
var maximumParts = 9e3;
|
|
70
|
-
var minimumPartSize = 10 * megabyte;
|
|
71
|
-
var uploadPartSize = (bytes) => {
|
|
72
|
-
const size = Number(bytes) || 0;
|
|
73
|
-
const required = Math.ceil(size / maximumParts);
|
|
74
|
-
const rounded = Math.ceil(required / megabyte) * megabyte;
|
|
75
|
-
return Math.max(minimumPartSize, rounded);
|
|
76
|
-
};
|
|
77
|
-
var uploadPartCount = (bytes) => {
|
|
78
|
-
const size = Number(bytes) || 0;
|
|
79
|
-
return Math.max(1, Math.ceil(size / uploadPartSize(size)));
|
|
80
|
-
};
|
|
81
59
|
// Annotate the CommonJS export names for ESM import in node:
|
|
82
60
|
0 && (module.exports = {
|
|
83
61
|
allowedMimes,
|
|
84
62
|
allowedUploadTypes,
|
|
85
63
|
isAllowedMime,
|
|
86
|
-
|
|
87
|
-
resolveUploadType,
|
|
88
|
-
uploadPartCount,
|
|
89
|
-
uploadPartSize
|
|
64
|
+
resolveUploadType
|
|
90
65
|
});
|
package/dist/upload.d.cts
CHANGED
|
@@ -15,12 +15,6 @@
|
|
|
15
15
|
//
|
|
16
16
|
// Why both helpers and not just one: api routes know (type, extension) but not
|
|
17
17
|
// the canonical mime; sync workers have the mime but not the original type tuple.
|
|
18
|
-
//
|
|
19
|
-
// A third consumer joined with presigned multipart uploads: the dashboard reads
|
|
20
|
-
// this same object to build its file picker's accept attribute and the uploader's
|
|
21
|
-
// client-side restrictions, so a wrong type is refused before two gigabytes move
|
|
22
|
-
// rather than after. That is the whole reason the list is not copied into
|
|
23
|
-
// app-web — four views of one list can't drift.
|
|
24
18
|
|
|
25
19
|
const allowedUploadTypes = {
|
|
26
20
|
application : {
|
|
@@ -33,11 +27,6 @@ const allowedUploadTypes = {
|
|
|
33
27
|
webp : 'image/webp'
|
|
34
28
|
},
|
|
35
29
|
video : {
|
|
36
|
-
// iPhones record .mov (HEVC) by default, so this is the single most
|
|
37
|
-
// likely video a merchant uploads. sync's storage.js already computes
|
|
38
|
-
// needsReencode for hevc/h265 and re-encodes to h264, so allowing it
|
|
39
|
-
// here is the only thing the pipeline was waiting on.
|
|
40
|
-
mov : 'video/quicktime',
|
|
41
30
|
mp4 : 'video/mp4'
|
|
42
31
|
}
|
|
43
32
|
};
|
|
@@ -66,51 +55,4 @@ const resolveUploadType = ( type, extension ) => {
|
|
|
66
55
|
|
|
67
56
|
const isAllowedMime = ( mime ) => allowedMimes.has( mime );
|
|
68
57
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// The ceiling for a presigned multipart upload. Video streams browser-to-bucket
|
|
72
|
-
// on that path rather than through the api, so this is a product decision
|
|
73
|
-
// rather than the fleet-protection one that keeps the single-request busboy
|
|
74
|
-
// route at 50MB.
|
|
75
|
-
//
|
|
76
|
-
// It lives here because both sides have to agree on it exactly: the dashboard
|
|
77
|
-
// rejects before transferring and the api rejects authoritatively, and if the
|
|
78
|
-
// two numbers drift the client blocks files the api would happily accept.
|
|
79
|
-
const maximumUploadBytes = ( 2048 * megabyte );
|
|
80
|
-
|
|
81
|
-
// S3 caps a multipart upload at 10,000 parts and requires every part except the
|
|
82
|
-
// last to be at least 5MB. A fixed part size therefore puts a silent ceiling on
|
|
83
|
-
// the maximum file, so the size is derived from the declared length with
|
|
84
|
-
// headroom against the hard limit.
|
|
85
|
-
//
|
|
86
|
-
// The 10MB floor is a request-volume decision, not an S3 one: a 2GB upload at
|
|
87
|
-
// 5MB parts is 410 signing calls, at 10MB it is 205.
|
|
88
|
-
//
|
|
89
|
-
// Both the api and the dashboard call this, and the dashboard *must* — Uppy
|
|
90
|
-
// builds its chunk list in the MultipartUploader constructor, which runs before
|
|
91
|
-
// createMultipartUpload is ever called, so a part size returned from the create
|
|
92
|
-
// endpoint arrives too late to chunk with. One function, two callers, no
|
|
93
|
-
// possibility of disagreeing about where the part boundaries fall.
|
|
94
|
-
const maximumParts = 9000;
|
|
95
|
-
const minimumPartSize = ( 10 * megabyte );
|
|
96
|
-
|
|
97
|
-
const uploadPartSize = ( bytes ) => {
|
|
98
|
-
|
|
99
|
-
const size = Number( bytes ) || 0;
|
|
100
|
-
const required = Math.ceil( size / maximumParts );
|
|
101
|
-
const rounded = Math.ceil( required / megabyte ) * megabyte;
|
|
102
|
-
|
|
103
|
-
return Math.max( minimumPartSize, rounded );
|
|
104
|
-
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
// An empty upload is still one part — S3 has no zero-part upload.
|
|
108
|
-
const uploadPartCount = ( bytes ) => {
|
|
109
|
-
|
|
110
|
-
const size = Number( bytes ) || 0;
|
|
111
|
-
|
|
112
|
-
return Math.max( 1, Math.ceil( size / uploadPartSize( size ) ) );
|
|
113
|
-
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
export { allowedMimes, allowedUploadTypes, isAllowedMime, maximumUploadBytes, resolveUploadType, uploadPartCount, uploadPartSize };
|
|
58
|
+
export { allowedMimes, allowedUploadTypes, isAllowedMime, resolveUploadType };
|
package/dist/upload.d.ts
CHANGED
|
@@ -15,12 +15,6 @@
|
|
|
15
15
|
//
|
|
16
16
|
// Why both helpers and not just one: api routes know (type, extension) but not
|
|
17
17
|
// the canonical mime; sync workers have the mime but not the original type tuple.
|
|
18
|
-
//
|
|
19
|
-
// A third consumer joined with presigned multipart uploads: the dashboard reads
|
|
20
|
-
// this same object to build its file picker's accept attribute and the uploader's
|
|
21
|
-
// client-side restrictions, so a wrong type is refused before two gigabytes move
|
|
22
|
-
// rather than after. That is the whole reason the list is not copied into
|
|
23
|
-
// app-web — four views of one list can't drift.
|
|
24
18
|
|
|
25
19
|
const allowedUploadTypes = {
|
|
26
20
|
application : {
|
|
@@ -33,11 +27,6 @@ const allowedUploadTypes = {
|
|
|
33
27
|
webp : 'image/webp'
|
|
34
28
|
},
|
|
35
29
|
video : {
|
|
36
|
-
// iPhones record .mov (HEVC) by default, so this is the single most
|
|
37
|
-
// likely video a merchant uploads. sync's storage.js already computes
|
|
38
|
-
// needsReencode for hevc/h265 and re-encodes to h264, so allowing it
|
|
39
|
-
// here is the only thing the pipeline was waiting on.
|
|
40
|
-
mov : 'video/quicktime',
|
|
41
30
|
mp4 : 'video/mp4'
|
|
42
31
|
}
|
|
43
32
|
};
|
|
@@ -66,51 +55,4 @@ const resolveUploadType = ( type, extension ) => {
|
|
|
66
55
|
|
|
67
56
|
const isAllowedMime = ( mime ) => allowedMimes.has( mime );
|
|
68
57
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// The ceiling for a presigned multipart upload. Video streams browser-to-bucket
|
|
72
|
-
// on that path rather than through the api, so this is a product decision
|
|
73
|
-
// rather than the fleet-protection one that keeps the single-request busboy
|
|
74
|
-
// route at 50MB.
|
|
75
|
-
//
|
|
76
|
-
// It lives here because both sides have to agree on it exactly: the dashboard
|
|
77
|
-
// rejects before transferring and the api rejects authoritatively, and if the
|
|
78
|
-
// two numbers drift the client blocks files the api would happily accept.
|
|
79
|
-
const maximumUploadBytes = ( 2048 * megabyte );
|
|
80
|
-
|
|
81
|
-
// S3 caps a multipart upload at 10,000 parts and requires every part except the
|
|
82
|
-
// last to be at least 5MB. A fixed part size therefore puts a silent ceiling on
|
|
83
|
-
// the maximum file, so the size is derived from the declared length with
|
|
84
|
-
// headroom against the hard limit.
|
|
85
|
-
//
|
|
86
|
-
// The 10MB floor is a request-volume decision, not an S3 one: a 2GB upload at
|
|
87
|
-
// 5MB parts is 410 signing calls, at 10MB it is 205.
|
|
88
|
-
//
|
|
89
|
-
// Both the api and the dashboard call this, and the dashboard *must* — Uppy
|
|
90
|
-
// builds its chunk list in the MultipartUploader constructor, which runs before
|
|
91
|
-
// createMultipartUpload is ever called, so a part size returned from the create
|
|
92
|
-
// endpoint arrives too late to chunk with. One function, two callers, no
|
|
93
|
-
// possibility of disagreeing about where the part boundaries fall.
|
|
94
|
-
const maximumParts = 9000;
|
|
95
|
-
const minimumPartSize = ( 10 * megabyte );
|
|
96
|
-
|
|
97
|
-
const uploadPartSize = ( bytes ) => {
|
|
98
|
-
|
|
99
|
-
const size = Number( bytes ) || 0;
|
|
100
|
-
const required = Math.ceil( size / maximumParts );
|
|
101
|
-
const rounded = Math.ceil( required / megabyte ) * megabyte;
|
|
102
|
-
|
|
103
|
-
return Math.max( minimumPartSize, rounded );
|
|
104
|
-
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
// An empty upload is still one part — S3 has no zero-part upload.
|
|
108
|
-
const uploadPartCount = ( bytes ) => {
|
|
109
|
-
|
|
110
|
-
const size = Number( bytes ) || 0;
|
|
111
|
-
|
|
112
|
-
return Math.max( 1, Math.ceil( size / uploadPartSize( size ) ) );
|
|
113
|
-
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
export { allowedMimes, allowedUploadTypes, isAllowedMime, maximumUploadBytes, resolveUploadType, uploadPartCount, uploadPartSize };
|
|
58
|
+
export { allowedMimes, allowedUploadTypes, isAllowedMime, resolveUploadType };
|
package/dist/upload.js
CHANGED
|
@@ -10,11 +10,6 @@ var allowedUploadTypes = {
|
|
|
10
10
|
webp: "image/webp"
|
|
11
11
|
},
|
|
12
12
|
video: {
|
|
13
|
-
// iPhones record .mov (HEVC) by default, so this is the single most
|
|
14
|
-
// likely video a merchant uploads. sync's storage.js already computes
|
|
15
|
-
// needsReencode for hevc/h265 and re-encodes to h264, so allowing it
|
|
16
|
-
// here is the only thing the pipeline was waiting on.
|
|
17
|
-
mov: "video/quicktime",
|
|
18
13
|
mp4: "video/mp4"
|
|
19
14
|
}
|
|
20
15
|
};
|
|
@@ -35,26 +30,9 @@ var resolveUploadType = (type, extension) => {
|
|
|
35
30
|
return mime;
|
|
36
31
|
};
|
|
37
32
|
var isAllowedMime = (mime) => allowedMimes.has(mime);
|
|
38
|
-
var megabyte = 1024 * 1024;
|
|
39
|
-
var maximumUploadBytes = 2048 * megabyte;
|
|
40
|
-
var maximumParts = 9e3;
|
|
41
|
-
var minimumPartSize = 10 * megabyte;
|
|
42
|
-
var uploadPartSize = (bytes) => {
|
|
43
|
-
const size = Number(bytes) || 0;
|
|
44
|
-
const required = Math.ceil(size / maximumParts);
|
|
45
|
-
const rounded = Math.ceil(required / megabyte) * megabyte;
|
|
46
|
-
return Math.max(minimumPartSize, rounded);
|
|
47
|
-
};
|
|
48
|
-
var uploadPartCount = (bytes) => {
|
|
49
|
-
const size = Number(bytes) || 0;
|
|
50
|
-
return Math.max(1, Math.ceil(size / uploadPartSize(size)));
|
|
51
|
-
};
|
|
52
33
|
export {
|
|
53
34
|
allowedMimes,
|
|
54
35
|
allowedUploadTypes,
|
|
55
36
|
isAllowedMime,
|
|
56
|
-
|
|
57
|
-
resolveUploadType,
|
|
58
|
-
uploadPartCount,
|
|
59
|
-
uploadPartSize
|
|
37
|
+
resolveUploadType
|
|
60
38
|
};
|
package/package.json
CHANGED