@rebalworks/transfer-sdk 0.1.1
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/LICENSE +8 -0
- package/README.md +110 -0
- package/dist/chunk-put-worker.cjs +1 -0
- package/dist/chunk-put-worker.js +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +130 -0
- package/dist/index.d.ts +130 -0
- package/dist/index.js +1 -0
- package/dist/sha256-worker.cjs +6 -0
- package/dist/sha256-worker.js +6 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
rebalTransfer — Proprietary Software License
|
|
2
|
+
Copyright (c) 2026 rebalworks CO., LTD. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
This package is proprietary and confidential. Unauthorized copying,
|
|
5
|
+
modification, distribution, or use of this software, via any medium, is
|
|
6
|
+
strictly prohibited without prior written permission from rebalworks CO., LTD.
|
|
7
|
+
|
|
8
|
+
For licensing inquiries, contact: byhaejin@f-m.kr
|
package/README.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# @rebalworks/transfer-sdk
|
|
2
|
+
|
|
3
|
+
Browser file-transfer SDK for rebalTransfer.
|
|
4
|
+
|
|
5
|
+
Small, typed, and UI-free. Bring your own interface and let the SDK handle
|
|
6
|
+
session creation, chunk upload, progress events, retry, resume, and abort.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @rebalworks/transfer-sdk
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
| Feature | What it does |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| Chunk upload | Splits a `File` into chunks and uploads them through the rebalTransfer API. |
|
|
19
|
+
| Progress events | Emits upload speed, percentage, ETA, and completed chunk events. |
|
|
20
|
+
| Abort | Cancels in-flight requests and asks the server to clean up the session. |
|
|
21
|
+
| Retry | Retries transient failures with backoff. |
|
|
22
|
+
| Resume | Skips chunks already accepted by the server. |
|
|
23
|
+
| Storage profiles | Selects a backend profile such as local storage, S3, or Google Drive. |
|
|
24
|
+
| Worker mode | Uses browser workers when available for large-file processing. |
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { createTransferSession } from '@rebalworks/transfer-sdk';
|
|
30
|
+
|
|
31
|
+
const handle = createTransferSession({
|
|
32
|
+
file,
|
|
33
|
+
apiBase: 'https://transfer.example.com/api/v1/sessions',
|
|
34
|
+
storageProfile: 'google-drive-main',
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
handle.on('progress', (event) => {
|
|
38
|
+
console.log(`${event.percent.toFixed(1)}%`);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
handle.on('chunk:done', (event) => {
|
|
42
|
+
console.log(`chunk ${event.partNumber}/${event.totalParts}`);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const session = await handle.done;
|
|
46
|
+
console.log(session.sessionId);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Abort
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
const handle = createTransferSession({ file });
|
|
53
|
+
|
|
54
|
+
cancelButton.addEventListener('click', () => {
|
|
55
|
+
void handle.abort();
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Resume
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
const handle = createTransferSession({
|
|
63
|
+
file,
|
|
64
|
+
resumeSessionId: previousSessionId,
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Storage Profile
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const handle = createTransferSession({
|
|
72
|
+
file,
|
|
73
|
+
storageProfile: 'google-drive-main',
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The SDK forwards the profile name to the server. Profile validation and storage
|
|
78
|
+
routing are handled by rebalTransfer.
|
|
79
|
+
|
|
80
|
+
## API
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
createTransferSession(options): TransferSessionHandle
|
|
84
|
+
listStorageProfiles(options): Promise<StorageProfile[]>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### `CreateTransferSessionOptions`
|
|
88
|
+
|
|
89
|
+
| Option | Type | Description |
|
|
90
|
+
| --- | --- | --- |
|
|
91
|
+
| `file` | `File` | File to upload. |
|
|
92
|
+
| `apiBase` | `string` | Session API endpoint. Defaults to `/api/v1/sessions` on the current origin. |
|
|
93
|
+
| `authToken` | `string` | Bearer token for protected APIs. |
|
|
94
|
+
| `storageProfile` | `string` | Server-side storage profile name. |
|
|
95
|
+
| `chunkSize` | `number` | Chunk size in bytes. |
|
|
96
|
+
| `retries` | `number` | Retry count for transient failures. |
|
|
97
|
+
| `sha256` | `string` | Precomputed SHA-256 hex string. |
|
|
98
|
+
| `resumeSessionId` | `string` | Existing session id to resume. |
|
|
99
|
+
| `workerPoolSize` | `number` | Number of upload workers. Defaults to `1`. |
|
|
100
|
+
| `signal` | `AbortSignal` | External abort signal. |
|
|
101
|
+
|
|
102
|
+
## Package Contents
|
|
103
|
+
|
|
104
|
+
The npm package contains minified JavaScript, public TypeScript declarations,
|
|
105
|
+
README, LICENSE, and package metadata only. It does not include source maps,
|
|
106
|
+
test files, or original TypeScript sources.
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
Proprietary. See `LICENSE`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';function p(e,r){return `${w(e)}/${r}`}function m(e,r,o){return `${p(e,r)}/chunks/${o}`}function y(e){return e===void 0||e.length===0?{}:{Authorization:`Bearer ${e}`}}function g(e){return `bytes ${e.start}-${e.end-1}/${e.total}`}function w(e){return e.replace(/\/$/,"")}var l=class extends Error{name="ApiError";status;responseBody;constructor(r,o,t){super(t),this.status=r,this.responseBody=o;}get retryable(){return this.status===0||this.status===408||this.status===429||this.status>=500&&this.status<600}};var P={maxRetries:3,initialDelayMs:100,backoffMultiplier:2,maxDelayMs:5e3,jitterRatio:.25};async function b(e,r,o){let t={...P,...r},n;for(let s=0;s<=t.maxRetries;s++){if(o.aborted)throw o.reason instanceof Error?o.reason:new DOMException("Aborted","AbortError");try{return await e()}catch(a){if(n=a,a instanceof Error&&a.name==="AbortError"||a instanceof l&&!a.retryable)throw a;if(s===t.maxRetries)break;let d=Math.min(t.initialDelayMs*Math.pow(t.backoffMultiplier,s),t.maxDelayMs),i=d*t.jitterRatio*(Math.random()*2-1),u=Math.max(0,Math.round(d+i));await R(u,o);}}throw n}function R(e,r){return new Promise((o,t)=>{if(r.aborted){t(r.reason instanceof Error?r.reason:new DOMException("Aborted","AbortError"));return}let n=setTimeout(()=>{r.removeEventListener("abort",s),o();},e),s=()=>{clearTimeout(n),r.removeEventListener("abort",s),t(r.reason instanceof Error?r.reason:new DOMException("Aborted","AbortError"));};r.addEventListener("abort",s,{once:true});})}var c=null,f=self;f.addEventListener("message",e=>{let r=e.data;if(r.type==="abort"){c?.abort();return}if(r.type==="put"){c=new AbortController;let o=r.partNumber;x(r).catch(t=>{let n=t instanceof Error?t:new Error(String(t)),s=c?.signal,a=n.name==="AbortError"||s?.aborted===true,d=n instanceof l?n.status:void 0,i=n instanceof l?n.retryable:!a;h({type:"error",partNumber:o,error:{name:n.name,message:n.message,status:d,cancelled:a,retryable:i}});});}});async function x(e){let{apiBase:r,authToken:o,sessionId:t,partNumber:n,contentRange:s,blob:a,retries:d}=e,i=c.signal,u=performance.now();await b(()=>E(r,o,t,n,s,a,i),d,i);let k=performance.now()-u;h({type:"put-done",partNumber:n,bytesUploaded:s.end-s.start,elapsedMs:k});}async function E(e,r,o,t,n,s,a){let d={method:"PUT",headers:{"Content-Type":"application/octet-stream","Content-Range":g(n),...y(r)},body:s,signal:a},i;try{i=await fetch(m(e,o,t),d);}catch(u){throw u instanceof Error&&u.name==="AbortError"?u:new l(0,"",`network error: ${u.message}`)}if(!i.ok){let u="";try{u=await i.text();}catch{}throw new l(i.status,u,`HTTP ${i.status} ${i.statusText} \u2014 ${u||"(no body)"}`)}}function h(e){f.postMessage(e);}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function p(e,r){return `${w(e)}/${r}`}function m(e,r,o){return `${p(e,r)}/chunks/${o}`}function y(e){return e===void 0||e.length===0?{}:{Authorization:`Bearer ${e}`}}function g(e){return `bytes ${e.start}-${e.end-1}/${e.total}`}function w(e){return e.replace(/\/$/,"")}var l=class extends Error{name="ApiError";status;responseBody;constructor(r,o,t){super(t),this.status=r,this.responseBody=o;}get retryable(){return this.status===0||this.status===408||this.status===429||this.status>=500&&this.status<600}};var P={maxRetries:3,initialDelayMs:100,backoffMultiplier:2,maxDelayMs:5e3,jitterRatio:.25};async function b(e,r,o){let t={...P,...r},n;for(let s=0;s<=t.maxRetries;s++){if(o.aborted)throw o.reason instanceof Error?o.reason:new DOMException("Aborted","AbortError");try{return await e()}catch(a){if(n=a,a instanceof Error&&a.name==="AbortError"||a instanceof l&&!a.retryable)throw a;if(s===t.maxRetries)break;let d=Math.min(t.initialDelayMs*Math.pow(t.backoffMultiplier,s),t.maxDelayMs),i=d*t.jitterRatio*(Math.random()*2-1),u=Math.max(0,Math.round(d+i));await R(u,o);}}throw n}function R(e,r){return new Promise((o,t)=>{if(r.aborted){t(r.reason instanceof Error?r.reason:new DOMException("Aborted","AbortError"));return}let n=setTimeout(()=>{r.removeEventListener("abort",s),o();},e),s=()=>{clearTimeout(n),r.removeEventListener("abort",s),t(r.reason instanceof Error?r.reason:new DOMException("Aborted","AbortError"));};r.addEventListener("abort",s,{once:true});})}var c=null,f=self;f.addEventListener("message",e=>{let r=e.data;if(r.type==="abort"){c?.abort();return}if(r.type==="put"){c=new AbortController;let o=r.partNumber;x(r).catch(t=>{let n=t instanceof Error?t:new Error(String(t)),s=c?.signal,a=n.name==="AbortError"||s?.aborted===true,d=n instanceof l?n.status:void 0,i=n instanceof l?n.retryable:!a;h({type:"error",partNumber:o,error:{name:n.name,message:n.message,status:d,cancelled:a,retryable:i}});});}});async function x(e){let{apiBase:r,authToken:o,sessionId:t,partNumber:n,contentRange:s,blob:a,retries:d}=e,i=c.signal,u=performance.now();await b(()=>E(r,o,t,n,s,a,i),d,i);let k=performance.now()-u;h({type:"put-done",partNumber:n,bytesUploaded:s.end-s.start,elapsedMs:k});}async function E(e,r,o,t,n,s,a){let d={method:"PUT",headers:{"Content-Type":"application/octet-stream","Content-Range":g(n),...y(r)},body:s,signal:a},i;try{i=await fetch(m(e,o,t),d);}catch(u){throw u instanceof Error&&u.name==="AbortError"?u:new l(0,"",`network error: ${u.message}`)}if(!i.ok){let u="";try{u=await i.text();}catch{}throw new l(i.status,u,`HTTP ${i.status} ${i.statusText} \u2014 ${u||"(no body)"}`)}}function h(e){f.postMessage(e);}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;var U=class{listeners=new Map;on(r,t){let s=this.listeners.get(r)??new Set;return s.add(t),this.listeners.set(r,s),()=>this.off(r,t)}once(r,t){let s=this.on(r,o=>{s(),t(o);});return s}off(r,t){let s=this.listeners.get(r);s!==void 0&&(s.delete(t),s.size===0&&this.listeners.delete(r));}emit(r,t){let s=this.listeners.get(r);if(s!==void 0)for(let o of [...s])try{o(t);}catch(n){console.error(`[EventEmitter] listener for "${String(r)}" threw:`,n);}}removeAllListeners(){this.listeners.clear();}};function x(e,r){return `${G(e)}/${r}`}function j(e,r){return `${x(e,r)}/progress`}function K(e,r,t){return `${x(e,r)}/chunks/${t}`}function F(e,r){return `${x(e,r)}/commit`}function q(e){return `${G(e)}/storage-profiles`}function T(e){return e===void 0||e.length===0?{}:{Authorization:`Bearer ${e}`}}function _(e){return `bytes ${e.start}-${e.end-1}/${e.total}`}function G(e){return e.replace(/\/$/,"")}var P=class extends Error{name="ApiError";status;responseBody;constructor(r,t,s){super(s),this.status=r,this.responseBody=t;}get retryable(){return this.status===0||this.status===408||this.status===429||this.status>=500&&this.status<600}};async function C(e,r,t){let s;try{s=await fetch(e,{...r,signal:t});}catch(n){throw n instanceof Error&&n.name==="AbortError"?n:new P(0,"",`network error: ${n.message}`)}if(!s.ok){let n="";try{n=await s.text();}catch{}throw new P(s.status,n,`HTTP ${s.status} ${s.statusText} \u2014 ${n||"(no body)"}`)}if((s.headers.get("content-type")??"").includes("application/json"))return s.json()}async function Y(e,r,t,s){return await C(e,{method:"POST",headers:{"Content-Type":"application/json",...T(s)},body:JSON.stringify(r)},t)}async function J(e,r,t,s){return await C(x(e,r),{method:"GET",headers:T(s)},t)}async function V(e,r,t,s){return await C(j(e,r),{method:"GET",headers:T(s)},t)}async function Z(e,r,t,s,o,n,i){return await C(K(e,r,t),{method:"PUT",headers:{"Content-Type":"application/octet-stream","Content-Range":_(s),...T(i)},body:o},n)}async function Q(e,r,t,s){return await C(F(e,r),{method:"POST",headers:T(s)},t)}async function X(e,r,t,s){await C(x(e,r),{method:"DELETE",headers:T(s)},t);}async function ee(e,r,t){return await C(q(e),{method:"GET",headers:T(t)},r)}function $(){return !(typeof Worker>"u")}async function re(e){if(!$())throw new Error("Web Worker not supported in this environment");let r=performance.now(),t=await ce(e);if(e.signal.aborted)throw A(e.signal);let s=Math.ceil(e.file.size/e.chunkSize),o=await e.transport.createSession({fileName:e.file.name,totalBytes:e.file.size,totalParts:s,sha256:t,chunkSize:e.chunkSize,storageProfile:e.storageProfile},e.signal);if(e.onSessionCreated(o),await fe(o.sessionId,s,e),e.signal.aborted)throw A(e.signal);let n=await e.transport.commitSession(o.sessionId,e.signal),i=performance.now()-r,l=e.file.size/(1024*1024)/(i/1e3);return {finalSession:n,totalElapsedMs:i,averageMbps:l}}function ce(e){return new Promise((r,t)=>{let s=new Worker(new URL("./sha256-worker.js",(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))),{type:"module"}),o=false,n=f=>{if(!o){o=true,s.removeEventListener("message",v),s.removeEventListener("error",l),s.removeEventListener("messageerror",h);try{s.terminate();}catch{}f();}},i=()=>{try{let f={type:"abort"};s.postMessage(f);}catch{}n(()=>t(A(e.signal)));};if(e.signal.aborted){i();return}e.signal.addEventListener("abort",i,{once:true});let l=f=>n(()=>t(new Error(`SHA-256 Worker error: ${f.message??"(no message)"}`))),h=f=>n(()=>t(new Error(`SHA-256 Worker messageerror: ${String(f.data)}`))),v=f=>{let p=f.data;switch(p.type){case "sha256-progress":e.onSha256Progress({bytesProcessed:p.bytesProcessed,totalBytes:p.totalBytes});return;case "sha256-done":e.signal.removeEventListener("abort",i),n(()=>r(p.sha256));return;case "error":{if(e.signal.removeEventListener("abort",i),p.error.cancelled)n(()=>t(A(e.signal)));else {let y=new Error(p.error.message);y.name=p.error.name,n(()=>t(y));}return}default:{let y=p;n(()=>t(new Error(`Unknown sha256-worker message: ${JSON.stringify(y)}`)));}}};s.addEventListener("message",v),s.addEventListener("error",l),s.addEventListener("messageerror",h);let w={type:"start",file:e.file};try{s.postMessage(w);}catch(f){n(()=>t(f instanceof Error?f:new Error(String(f))));}})}function fe(e,r,t){let s=Number.isFinite(t.workerPoolSize)&&t.workerPoolSize>=1?Math.floor(t.workerPoolSize):1,o=Math.max(1,Math.min(s,Math.max(1,r)));return new Promise((n,i)=>{let l=[],h=[],v=new Set,w=0,f=false;for(let u=1;u<=r;u++)h.push(u);let p=u=>{if(!f){f=true;for(let a of l){try{let m={type:"abort"};a.worker.postMessage(m);}catch{}try{a.worker.terminate();}catch{}}t.signal.removeEventListener("abort",y),u();}},y=()=>p(()=>i(A(t.signal)));if(t.signal.aborted){y();return}t.signal.addEventListener("abort",y,{once:true});let S=u=>{if(f)return;let a=h.shift();if(a===void 0){u.busyPart=null,w>=r&&l.every(E=>E.busyPart===null)&&p(()=>n());return}u.busyPart=a;let m=(a-1)*t.chunkSize,b=Math.min(m+t.chunkSize,t.file.size),k=t.file.slice(m,b),R={type:"put",apiBase:t.apiBase,authToken:t.authToken,sessionId:e,partNumber:a,contentRange:{start:m,end:b,total:t.file.size},blob:k,retries:{maxRetries:t.retries}};try{u.worker.postMessage(R);}catch(E){p(()=>i(E instanceof Error?E:new Error(String(E))));}},M=(u,a)=>{switch(a.type){case "put-done":w++,t.onChunkComplete({partNumber:a.partNumber,bytesUploaded:a.bytesUploaded,elapsedMs:a.elapsedMs}),S(u);return;case "error":{if(a.error.cancelled){p(()=>i(A(t.signal)));return}if(a.error.retryable&&!v.has(a.partNumber)&&l.length>1){v.add(a.partNumber),h.push(a.partNumber),z(u);for(let b of l.filter(k=>k.busyPart===null))S(b);return}let m=a.error.status!==void 0?new P(a.error.status,"",a.error.message):Object.assign(new Error(a.error.message),{name:a.error.name});p(()=>i(m));return}default:{let m=a;p(()=>i(new Error(`Unknown chunk-put-worker message: ${JSON.stringify(m)}`)));}}};for(let u=0;u<o;u++){let a=new Worker(new URL("./chunk-put-worker.js",(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))),{type:"module"}),m={worker:a,index:u,busyPart:null};l.push(m),a.addEventListener("message",b=>M(m,b.data)),a.addEventListener("error",b=>p(()=>i(new Error(`Chunk PUT Worker[${u}] error: ${b.message??"(no message)"}`)))),a.addEventListener("messageerror",b=>p(()=>i(new Error(`Chunk PUT Worker[${u}] messageerror: ${String(b.data)}`)))),S(m);}let z=u=>{let a=l.indexOf(u);a>=0&&l.splice(a,1),u.busyPart=null;try{let m={type:"abort"};u.worker.postMessage(m);}catch{}try{u.worker.terminate();}catch{}};})}function A(e){return e.reason instanceof Error?e.reason:new DOMException("Aborted","AbortError")}var te={maxRetries:3,initialDelayMs:100,backoffMultiplier:2,maxDelayMs:5e3,jitterRatio:.25};async function L(e,r,t){let s={...te,...r},o;for(let n=0;n<=s.maxRetries;n++){if(t.aborted)throw t.reason instanceof Error?t.reason:new DOMException("Aborted","AbortError");try{return await e()}catch(i){if(o=i,i instanceof Error&&i.name==="AbortError"||i instanceof P&&!i.retryable)throw i;if(n===s.maxRetries)break;let l=Math.min(s.initialDelayMs*Math.pow(s.backoffMultiplier,n),s.maxDelayMs),h=l*s.jitterRatio*(Math.random()*2-1),v=Math.max(0,Math.round(l+h));await pe(v,t);}}throw o}function pe(e,r){return new Promise((t,s)=>{if(r.aborted){s(r.reason instanceof Error?r.reason:new DOMException("Aborted","AbortError"));return}let o=setTimeout(()=>{r.removeEventListener("abort",n),t();},e),n=()=>{clearTimeout(o),r.removeEventListener("abort",n),s(r.reason instanceof Error?r.reason:new DOMException("Aborted","AbortError"));};r.addEventListener("abort",n,{once:true});})}async function se(e){for(let r=1;r<=e.totalParts;r++){if(e.signal.aborted)throw e.signal.reason instanceof Error?e.signal.reason:new DOMException("Aborted","AbortError");let t=(r-1)*e.chunkSize,s=Math.min(t+e.chunkSize,e.file.size);if(e.skipParts?.has(r))continue;let o=e.file.slice(t,s),n=performance.now();await L(()=>e.transport.uploadChunk(e.sessionId,r,{start:t,end:s,total:e.file.size},o,e.signal),e.retries,e.signal);let i=performance.now()-n;e.onChunkComplete({partNumber:r,bytesUploaded:s-t,elapsedMs:i});}}async function ne(e){if(e.size>524288e3)throw new Error(`file too large for main-thread SHA-256 (${me(e.size)} > 500MB). Use Web Worker streaming SHA-256 (P0 #5 track) \u2014 not yet implemented in SDK v0.1.`);let t=await e.arrayBuffer(),s=await crypto.subtle.digest("SHA-256",t);return [...new Uint8Array(s)].map(o=>o.toString(16).padStart(2,"0")).join("")}function me(e){if(e<1024)return `${e} B`;let r=["KB","MB","GB"],t=e/1024,s=0;for(;t>=1024&&s<r.length-1;)t/=1024,s++;return `${t.toFixed(1)} ${r[s]}`}var D=class{sha256;constructor(r){this.sha256=r;}async compute(){return this.sha256}},H=class{compute(r){return ne(r)}};function oe(e){return e===void 0?new H:new D(e)}var I=class{opts;constructor(r){this.opts=r;}async run(){let r=performance.now(),t=await this.opts.hashStrategy.compute(this.opts.file),s,o;if(this.opts.resumeSessionId!==void 0){o=await this.opts.transport.getSession(this.opts.resumeSessionId,this.opts.signal),ge(o,{file:this.opts.file,chunkSize:this.opts.chunkSize,totalParts:this.opts.totalParts,sha256:t});let h=await this.opts.transport.getProgress(this.opts.resumeSessionId,this.opts.signal);he(h,this.opts.resumeSessionId),s=new Set(h.completedParts),this.opts.onResumeProgress(ye(s,this.opts.file.size,this.opts.chunkSize));}else o=await this.opts.transport.createSession({fileName:this.opts.file.name,totalBytes:this.opts.file.size,totalParts:this.opts.totalParts,sha256:t,chunkSize:this.opts.chunkSize,storageProfile:this.opts.storageProfile},this.opts.signal);if(this.opts.onSessionCreated(o),await se({transport:this.opts.transport,sessionId:o.sessionId,file:this.opts.file,chunkSize:this.opts.chunkSize,totalParts:this.opts.totalParts,retries:{maxRetries:this.opts.retries},signal:this.opts.signal,skipParts:s,onChunkComplete:this.opts.onChunkComplete}),this.opts.signal.aborted)throw this.opts.signal.reason instanceof Error?this.opts.signal.reason:new DOMException("Aborted","AbortError");let n=await this.opts.transport.commitSession(o.sessionId,this.opts.signal),i=performance.now()-r,l=this.opts.file.size/(1024*1024)/(i/1e3);return {finalSession:n,totalElapsedMs:i,averageMbps:l}}};function ge(e,r){if(e.totalBytes!==r.file.size)throw new Error(`resume session file size mismatch: session=${e.totalBytes}, file=${r.file.size}`);if(e.chunkSize!==r.chunkSize)throw new Error(`resume session chunk size mismatch: session=${e.chunkSize}, requested=${r.chunkSize}`);if(e.totalParts!==r.totalParts)throw new Error(`resume session total parts mismatch: session=${e.totalParts}, requested=${r.totalParts}`);if(e.sha256.toLowerCase()!==r.sha256.toLowerCase())throw new Error("resume session SHA-256 mismatch");if(e.state==="COMMITTED")throw new Error("resume session is already committed");if(e.state==="ABORTED"||e.state==="FAILED")throw new Error(`resume session is terminal: ${e.state}`)}function he(e,r){if(e.sessionId!==r)throw new Error(`resume progress session mismatch: expected ${r}, got ${e.sessionId}`)}function ye(e,r,t){let s=0;for(let o of e){if(o<1)continue;let n=(o-1)*t;if(n>=r)continue;let i=Math.min(n+t,r);s+=i-n;}return Math.min(s,r)}var O=class{apiBase;authToken;constructor(r,t){this.apiBase=r,this.authToken=t;}createSession(r,t){return Y(this.apiBase,r,t,this.authToken)}getSession(r,t){return J(this.apiBase,r,t,this.authToken)}getProgress(r,t){return V(this.apiBase,r,t,this.authToken)}uploadChunk(r,t,s,o,n){return Z(this.apiBase,r,t,s,o,n,this.authToken)}commitSession(r,t){return Q(this.apiBase,r,t,this.authToken)}abortSession(r,t){return X(this.apiBase,r,t,this.authToken)}};var B=class{opts;constructor(r){this.opts=r;}run(){return re(this.opts)}};var Se=8*1024*1024,be=3,ke=1;function Ee(e){let r=e.apiBase??`${location.origin}/api/v1/sessions`,t=e.authToken,s=e.chunkSize??Se,o=e.storageProfile,n=e.retries??be,i=e.workerPoolSize??ke,l=e.file,h=Math.ceil(l.size/s),v=e.resumeSessionId,w=new O(r,t),f=new AbortController,p=e.signal?Pe(e.signal,f.signal):f.signal,y=false,S=new U,M,z,u=new Promise((d,c)=>{M=d,z=c;}),a,m,b=new Promise((d,c)=>{a=d,m=c;}),k=0,R=performance.now(),E,N=d=>{k+=d.bytesUploaded;let c=performance.now(),g=Math.max(.001,(c-R)/1e3),W=d.bytesUploaded/(1024*1024)/g;R=c,S.emit("chunk:done",{partNumber:d.partNumber,totalParts:h,bytesUploaded:d.bytesUploaded,elapsedMs:d.elapsedMs});let ae=l.size>0?k/l.size*100:100,le=Math.max(0,l.size-k),ue=W>0?le/(W*1024*1024):0,de={bytesSent:k,totalBytes:l.size,percent:ae,mbps:W,etaSeconds:ue};S.emit("progress",de);},ie=v===void 0&&e.forceMainThread!==true&&e.sha256===void 0&&$();return (async()=>{try{let c=await(ie?new B({apiBase:r,transport:w,authToken:t,file:l,chunkSize:s,storageProfile:o,retries:n,workerPoolSize:i,signal:p,onSha256Progress:g=>{S.emit("sha256:progress",{bytesProcessed:g.bytesProcessed,totalBytes:g.totalBytes,percent:g.totalBytes>0?g.bytesProcessed/g.totalBytes*100:0});},onSessionCreated:g=>{E=g.sessionId,M(g.sessionId);},onChunkComplete:N}):new I({transport:w,hashStrategy:oe(e.sha256),file:l,chunkSize:s,totalParts:h,storageProfile:o,retries:n,signal:p,resumeSessionId:v,onSessionCreated:g=>{E=g.sessionId,M(g.sessionId);},onResumeProgress:g=>{k=g,R=performance.now(),S.emit("progress",{bytesSent:k,totalBytes:l.size,percent:l.size>0?k/l.size*100:0,mbps:0,etaSeconds:0});},onChunkComplete:N})).run();S.emit("session:complete",{session:c.finalSession,totalElapsedMs:c.totalElapsedMs,averageMbps:c.averageMbps}),a(c.finalSession);}catch(d){let c=d instanceof Error?d:new Error(String(d)),g=y||c.name==="AbortError"||c instanceof P&&c.status===0&&p.aborted;S.emit("session:error",{error:c,cancelled:g}),E===void 0&&z(c),m(c);}})(),{sessionId:u,done:b,on:(d,c)=>S.on(d,c),once:(d,c)=>S.once(d,c),abort:async()=>{if(!y&&(y=true,f.abort(),E!==void 0))try{let d=new AbortController;await w.abortSession(E,d.signal);}catch(d){console.warn("[transfer-sdk] abort DELETE failed (non-critical):",d);}}}}function Pe(...e){if(typeof AbortSignal.any=="function")return AbortSignal.any(e);let r=new AbortController;for(let t of e){if(t.aborted)return r.abort(t.reason),r.signal;t.addEventListener("abort",()=>r.abort(t.reason),{once:true});}return r.signal}async function ve(e={}){let r=e.signal===void 0?new AbortController:void 0,t=e.signal??r?.signal;if(t===void 0)throw new Error("AbortSignal unavailable");return ee(e.apiRoot??we(),t,e.authToken)}function we(){let e=globalThis.location;return e===void 0?"/api/v1":`${e.origin}/api/v1`}var Xe="0.1.1";exports.ApiError=P;exports.DEFAULT_RETRY_OPTIONS=te;exports.EventEmitter=U;exports.VERSION=Xe;exports.createTransferSession=Ee;exports.listStorageProfiles=ve;exports.retryWithBackoff=L;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
type SessionState = 'INITIALIZING' | 'UPLOADING' | 'SCANNING' | 'COMMITTED' | 'ABORTED' | 'FAILED';
|
|
2
|
+
interface TransferSession {
|
|
3
|
+
readonly sessionId: string;
|
|
4
|
+
readonly fileName: string;
|
|
5
|
+
readonly totalBytes: number;
|
|
6
|
+
readonly totalParts: number;
|
|
7
|
+
readonly chunkSize: number;
|
|
8
|
+
readonly sha256: string;
|
|
9
|
+
readonly state: SessionState;
|
|
10
|
+
readonly storageProfile?: string | undefined;
|
|
11
|
+
readonly createdAt: string;
|
|
12
|
+
}
|
|
13
|
+
interface ChunkAck {
|
|
14
|
+
readonly sessionId: string;
|
|
15
|
+
readonly partNumber: number;
|
|
16
|
+
readonly accepted: boolean;
|
|
17
|
+
readonly bytesWritten: number;
|
|
18
|
+
readonly message?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
interface SessionProgress {
|
|
21
|
+
readonly sessionId: string;
|
|
22
|
+
readonly totalParts: number;
|
|
23
|
+
readonly completedCount: number;
|
|
24
|
+
readonly completedParts: readonly number[];
|
|
25
|
+
readonly state: SessionState;
|
|
26
|
+
}
|
|
27
|
+
interface StorageProfile {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly adapterId: string;
|
|
30
|
+
readonly type: 'filesystem' | 'object' | 'external-drive';
|
|
31
|
+
readonly defaultProfile: boolean;
|
|
32
|
+
readonly available: boolean;
|
|
33
|
+
}
|
|
34
|
+
interface ListStorageProfilesOptions {
|
|
35
|
+
readonly apiRoot?: string | undefined;
|
|
36
|
+
readonly authToken?: string | undefined;
|
|
37
|
+
readonly signal?: AbortSignal | undefined;
|
|
38
|
+
}
|
|
39
|
+
interface CreateTransferSessionOptions {
|
|
40
|
+
readonly file: File;
|
|
41
|
+
readonly apiBase?: string | undefined;
|
|
42
|
+
readonly authToken?: string | undefined;
|
|
43
|
+
readonly chunkSize?: number | undefined;
|
|
44
|
+
readonly storageProfile?: string | undefined;
|
|
45
|
+
readonly retries?: number | undefined;
|
|
46
|
+
readonly sha256?: string | undefined;
|
|
47
|
+
readonly signal?: AbortSignal | undefined;
|
|
48
|
+
readonly resumeSessionId?: string | undefined;
|
|
49
|
+
readonly forceMainThread?: boolean | undefined;
|
|
50
|
+
readonly workerPoolSize?: number | undefined;
|
|
51
|
+
}
|
|
52
|
+
interface ProgressEvent {
|
|
53
|
+
readonly bytesSent: number;
|
|
54
|
+
readonly totalBytes: number;
|
|
55
|
+
readonly percent: number;
|
|
56
|
+
readonly mbps: number;
|
|
57
|
+
readonly etaSeconds: number;
|
|
58
|
+
}
|
|
59
|
+
interface Sha256ProgressEvent {
|
|
60
|
+
readonly bytesProcessed: number;
|
|
61
|
+
readonly totalBytes: number;
|
|
62
|
+
readonly percent: number;
|
|
63
|
+
}
|
|
64
|
+
interface ChunkDoneEvent {
|
|
65
|
+
readonly partNumber: number;
|
|
66
|
+
readonly totalParts: number;
|
|
67
|
+
readonly bytesUploaded: number;
|
|
68
|
+
readonly elapsedMs: number;
|
|
69
|
+
}
|
|
70
|
+
interface SessionCompleteEvent {
|
|
71
|
+
readonly session: TransferSession;
|
|
72
|
+
readonly totalElapsedMs: number;
|
|
73
|
+
readonly averageMbps: number;
|
|
74
|
+
}
|
|
75
|
+
interface SessionErrorEvent {
|
|
76
|
+
readonly error: Error;
|
|
77
|
+
readonly cancelled: boolean;
|
|
78
|
+
readonly partNumber?: number | undefined;
|
|
79
|
+
readonly attempt?: number | undefined;
|
|
80
|
+
}
|
|
81
|
+
interface SessionEventMap {
|
|
82
|
+
progress: ProgressEvent;
|
|
83
|
+
'sha256:progress': Sha256ProgressEvent;
|
|
84
|
+
'chunk:done': ChunkDoneEvent;
|
|
85
|
+
'session:complete': SessionCompleteEvent;
|
|
86
|
+
'session:error': SessionErrorEvent;
|
|
87
|
+
}
|
|
88
|
+
interface TransferSessionHandle {
|
|
89
|
+
readonly sessionId: Promise<string>;
|
|
90
|
+
readonly done: Promise<TransferSession>;
|
|
91
|
+
on<K extends keyof SessionEventMap>(event: K, listener: (data: SessionEventMap[K]) => void): () => void;
|
|
92
|
+
once<K extends keyof SessionEventMap>(event: K, listener: (data: SessionEventMap[K]) => void): () => void;
|
|
93
|
+
abort(): Promise<void>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
declare function createTransferSession(options: CreateTransferSessionOptions): TransferSessionHandle;
|
|
97
|
+
|
|
98
|
+
type EventMap = Record<string, any>;
|
|
99
|
+
declare class EventEmitter<TEvents extends EventMap> {
|
|
100
|
+
private readonly listeners;
|
|
101
|
+
on<K extends keyof TEvents>(event: K, listener: (data: TEvents[K]) => void): () => void;
|
|
102
|
+
once<K extends keyof TEvents>(event: K, listener: (data: TEvents[K]) => void): () => void;
|
|
103
|
+
off<K extends keyof TEvents>(event: K, listener: (data: TEvents[K]) => void): void;
|
|
104
|
+
emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void;
|
|
105
|
+
removeAllListeners(): void;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
declare function listStorageProfiles(options?: ListStorageProfilesOptions): Promise<readonly StorageProfile[]>;
|
|
109
|
+
|
|
110
|
+
interface RetryOptions {
|
|
111
|
+
readonly maxRetries: number;
|
|
112
|
+
readonly initialDelayMs: number;
|
|
113
|
+
readonly backoffMultiplier: number;
|
|
114
|
+
readonly maxDelayMs: number;
|
|
115
|
+
readonly jitterRatio: number;
|
|
116
|
+
}
|
|
117
|
+
declare const DEFAULT_RETRY_OPTIONS: RetryOptions;
|
|
118
|
+
declare function retryWithBackoff<T>(task: () => Promise<T>, options: Partial<RetryOptions>, signal: AbortSignal): Promise<T>;
|
|
119
|
+
|
|
120
|
+
declare class ApiError extends Error {
|
|
121
|
+
readonly name = "ApiError";
|
|
122
|
+
readonly status: number;
|
|
123
|
+
readonly responseBody: string;
|
|
124
|
+
constructor(status: number, responseBody: string, message: string);
|
|
125
|
+
get retryable(): boolean;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
declare const VERSION = "0.1.1";
|
|
129
|
+
|
|
130
|
+
export { ApiError, type ChunkAck, type ChunkDoneEvent, type CreateTransferSessionOptions, DEFAULT_RETRY_OPTIONS, EventEmitter, type ListStorageProfilesOptions, type ProgressEvent, type RetryOptions, type SessionCompleteEvent, type SessionErrorEvent, type SessionEventMap, type SessionProgress, type SessionState, type Sha256ProgressEvent, type StorageProfile, type TransferSession, type TransferSessionHandle, VERSION, createTransferSession, listStorageProfiles, retryWithBackoff };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
type SessionState = 'INITIALIZING' | 'UPLOADING' | 'SCANNING' | 'COMMITTED' | 'ABORTED' | 'FAILED';
|
|
2
|
+
interface TransferSession {
|
|
3
|
+
readonly sessionId: string;
|
|
4
|
+
readonly fileName: string;
|
|
5
|
+
readonly totalBytes: number;
|
|
6
|
+
readonly totalParts: number;
|
|
7
|
+
readonly chunkSize: number;
|
|
8
|
+
readonly sha256: string;
|
|
9
|
+
readonly state: SessionState;
|
|
10
|
+
readonly storageProfile?: string | undefined;
|
|
11
|
+
readonly createdAt: string;
|
|
12
|
+
}
|
|
13
|
+
interface ChunkAck {
|
|
14
|
+
readonly sessionId: string;
|
|
15
|
+
readonly partNumber: number;
|
|
16
|
+
readonly accepted: boolean;
|
|
17
|
+
readonly bytesWritten: number;
|
|
18
|
+
readonly message?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
interface SessionProgress {
|
|
21
|
+
readonly sessionId: string;
|
|
22
|
+
readonly totalParts: number;
|
|
23
|
+
readonly completedCount: number;
|
|
24
|
+
readonly completedParts: readonly number[];
|
|
25
|
+
readonly state: SessionState;
|
|
26
|
+
}
|
|
27
|
+
interface StorageProfile {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly adapterId: string;
|
|
30
|
+
readonly type: 'filesystem' | 'object' | 'external-drive';
|
|
31
|
+
readonly defaultProfile: boolean;
|
|
32
|
+
readonly available: boolean;
|
|
33
|
+
}
|
|
34
|
+
interface ListStorageProfilesOptions {
|
|
35
|
+
readonly apiRoot?: string | undefined;
|
|
36
|
+
readonly authToken?: string | undefined;
|
|
37
|
+
readonly signal?: AbortSignal | undefined;
|
|
38
|
+
}
|
|
39
|
+
interface CreateTransferSessionOptions {
|
|
40
|
+
readonly file: File;
|
|
41
|
+
readonly apiBase?: string | undefined;
|
|
42
|
+
readonly authToken?: string | undefined;
|
|
43
|
+
readonly chunkSize?: number | undefined;
|
|
44
|
+
readonly storageProfile?: string | undefined;
|
|
45
|
+
readonly retries?: number | undefined;
|
|
46
|
+
readonly sha256?: string | undefined;
|
|
47
|
+
readonly signal?: AbortSignal | undefined;
|
|
48
|
+
readonly resumeSessionId?: string | undefined;
|
|
49
|
+
readonly forceMainThread?: boolean | undefined;
|
|
50
|
+
readonly workerPoolSize?: number | undefined;
|
|
51
|
+
}
|
|
52
|
+
interface ProgressEvent {
|
|
53
|
+
readonly bytesSent: number;
|
|
54
|
+
readonly totalBytes: number;
|
|
55
|
+
readonly percent: number;
|
|
56
|
+
readonly mbps: number;
|
|
57
|
+
readonly etaSeconds: number;
|
|
58
|
+
}
|
|
59
|
+
interface Sha256ProgressEvent {
|
|
60
|
+
readonly bytesProcessed: number;
|
|
61
|
+
readonly totalBytes: number;
|
|
62
|
+
readonly percent: number;
|
|
63
|
+
}
|
|
64
|
+
interface ChunkDoneEvent {
|
|
65
|
+
readonly partNumber: number;
|
|
66
|
+
readonly totalParts: number;
|
|
67
|
+
readonly bytesUploaded: number;
|
|
68
|
+
readonly elapsedMs: number;
|
|
69
|
+
}
|
|
70
|
+
interface SessionCompleteEvent {
|
|
71
|
+
readonly session: TransferSession;
|
|
72
|
+
readonly totalElapsedMs: number;
|
|
73
|
+
readonly averageMbps: number;
|
|
74
|
+
}
|
|
75
|
+
interface SessionErrorEvent {
|
|
76
|
+
readonly error: Error;
|
|
77
|
+
readonly cancelled: boolean;
|
|
78
|
+
readonly partNumber?: number | undefined;
|
|
79
|
+
readonly attempt?: number | undefined;
|
|
80
|
+
}
|
|
81
|
+
interface SessionEventMap {
|
|
82
|
+
progress: ProgressEvent;
|
|
83
|
+
'sha256:progress': Sha256ProgressEvent;
|
|
84
|
+
'chunk:done': ChunkDoneEvent;
|
|
85
|
+
'session:complete': SessionCompleteEvent;
|
|
86
|
+
'session:error': SessionErrorEvent;
|
|
87
|
+
}
|
|
88
|
+
interface TransferSessionHandle {
|
|
89
|
+
readonly sessionId: Promise<string>;
|
|
90
|
+
readonly done: Promise<TransferSession>;
|
|
91
|
+
on<K extends keyof SessionEventMap>(event: K, listener: (data: SessionEventMap[K]) => void): () => void;
|
|
92
|
+
once<K extends keyof SessionEventMap>(event: K, listener: (data: SessionEventMap[K]) => void): () => void;
|
|
93
|
+
abort(): Promise<void>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
declare function createTransferSession(options: CreateTransferSessionOptions): TransferSessionHandle;
|
|
97
|
+
|
|
98
|
+
type EventMap = Record<string, any>;
|
|
99
|
+
declare class EventEmitter<TEvents extends EventMap> {
|
|
100
|
+
private readonly listeners;
|
|
101
|
+
on<K extends keyof TEvents>(event: K, listener: (data: TEvents[K]) => void): () => void;
|
|
102
|
+
once<K extends keyof TEvents>(event: K, listener: (data: TEvents[K]) => void): () => void;
|
|
103
|
+
off<K extends keyof TEvents>(event: K, listener: (data: TEvents[K]) => void): void;
|
|
104
|
+
emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void;
|
|
105
|
+
removeAllListeners(): void;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
declare function listStorageProfiles(options?: ListStorageProfilesOptions): Promise<readonly StorageProfile[]>;
|
|
109
|
+
|
|
110
|
+
interface RetryOptions {
|
|
111
|
+
readonly maxRetries: number;
|
|
112
|
+
readonly initialDelayMs: number;
|
|
113
|
+
readonly backoffMultiplier: number;
|
|
114
|
+
readonly maxDelayMs: number;
|
|
115
|
+
readonly jitterRatio: number;
|
|
116
|
+
}
|
|
117
|
+
declare const DEFAULT_RETRY_OPTIONS: RetryOptions;
|
|
118
|
+
declare function retryWithBackoff<T>(task: () => Promise<T>, options: Partial<RetryOptions>, signal: AbortSignal): Promise<T>;
|
|
119
|
+
|
|
120
|
+
declare class ApiError extends Error {
|
|
121
|
+
readonly name = "ApiError";
|
|
122
|
+
readonly status: number;
|
|
123
|
+
readonly responseBody: string;
|
|
124
|
+
constructor(status: number, responseBody: string, message: string);
|
|
125
|
+
get retryable(): boolean;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
declare const VERSION = "0.1.1";
|
|
129
|
+
|
|
130
|
+
export { ApiError, type ChunkAck, type ChunkDoneEvent, type CreateTransferSessionOptions, DEFAULT_RETRY_OPTIONS, EventEmitter, type ListStorageProfilesOptions, type ProgressEvent, type RetryOptions, type SessionCompleteEvent, type SessionErrorEvent, type SessionEventMap, type SessionProgress, type SessionState, type Sha256ProgressEvent, type StorageProfile, type TransferSession, type TransferSessionHandle, VERSION, createTransferSession, listStorageProfiles, retryWithBackoff };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var U=class{listeners=new Map;on(r,t){let s=this.listeners.get(r)??new Set;return s.add(t),this.listeners.set(r,s),()=>this.off(r,t)}once(r,t){let s=this.on(r,o=>{s(),t(o);});return s}off(r,t){let s=this.listeners.get(r);s!==void 0&&(s.delete(t),s.size===0&&this.listeners.delete(r));}emit(r,t){let s=this.listeners.get(r);if(s!==void 0)for(let o of [...s])try{o(t);}catch(n){console.error(`[EventEmitter] listener for "${String(r)}" threw:`,n);}}removeAllListeners(){this.listeners.clear();}};function x(e,r){return `${G(e)}/${r}`}function j(e,r){return `${x(e,r)}/progress`}function K(e,r,t){return `${x(e,r)}/chunks/${t}`}function F(e,r){return `${x(e,r)}/commit`}function q(e){return `${G(e)}/storage-profiles`}function T(e){return e===void 0||e.length===0?{}:{Authorization:`Bearer ${e}`}}function _(e){return `bytes ${e.start}-${e.end-1}/${e.total}`}function G(e){return e.replace(/\/$/,"")}var P=class extends Error{name="ApiError";status;responseBody;constructor(r,t,s){super(s),this.status=r,this.responseBody=t;}get retryable(){return this.status===0||this.status===408||this.status===429||this.status>=500&&this.status<600}};async function C(e,r,t){let s;try{s=await fetch(e,{...r,signal:t});}catch(n){throw n instanceof Error&&n.name==="AbortError"?n:new P(0,"",`network error: ${n.message}`)}if(!s.ok){let n="";try{n=await s.text();}catch{}throw new P(s.status,n,`HTTP ${s.status} ${s.statusText} \u2014 ${n||"(no body)"}`)}if((s.headers.get("content-type")??"").includes("application/json"))return s.json()}async function Y(e,r,t,s){return await C(e,{method:"POST",headers:{"Content-Type":"application/json",...T(s)},body:JSON.stringify(r)},t)}async function J(e,r,t,s){return await C(x(e,r),{method:"GET",headers:T(s)},t)}async function V(e,r,t,s){return await C(j(e,r),{method:"GET",headers:T(s)},t)}async function Z(e,r,t,s,o,n,i){return await C(K(e,r,t),{method:"PUT",headers:{"Content-Type":"application/octet-stream","Content-Range":_(s),...T(i)},body:o},n)}async function Q(e,r,t,s){return await C(F(e,r),{method:"POST",headers:T(s)},t)}async function X(e,r,t,s){await C(x(e,r),{method:"DELETE",headers:T(s)},t);}async function ee(e,r,t){return await C(q(e),{method:"GET",headers:T(t)},r)}function $(){return !(typeof Worker>"u")}async function re(e){if(!$())throw new Error("Web Worker not supported in this environment");let r=performance.now(),t=await ce(e);if(e.signal.aborted)throw A(e.signal);let s=Math.ceil(e.file.size/e.chunkSize),o=await e.transport.createSession({fileName:e.file.name,totalBytes:e.file.size,totalParts:s,sha256:t,chunkSize:e.chunkSize,storageProfile:e.storageProfile},e.signal);if(e.onSessionCreated(o),await fe(o.sessionId,s,e),e.signal.aborted)throw A(e.signal);let n=await e.transport.commitSession(o.sessionId,e.signal),i=performance.now()-r,l=e.file.size/(1024*1024)/(i/1e3);return {finalSession:n,totalElapsedMs:i,averageMbps:l}}function ce(e){return new Promise((r,t)=>{let s=new Worker(new URL("./sha256-worker.js",import.meta.url),{type:"module"}),o=false,n=f=>{if(!o){o=true,s.removeEventListener("message",v),s.removeEventListener("error",l),s.removeEventListener("messageerror",h);try{s.terminate();}catch{}f();}},i=()=>{try{let f={type:"abort"};s.postMessage(f);}catch{}n(()=>t(A(e.signal)));};if(e.signal.aborted){i();return}e.signal.addEventListener("abort",i,{once:true});let l=f=>n(()=>t(new Error(`SHA-256 Worker error: ${f.message??"(no message)"}`))),h=f=>n(()=>t(new Error(`SHA-256 Worker messageerror: ${String(f.data)}`))),v=f=>{let p=f.data;switch(p.type){case "sha256-progress":e.onSha256Progress({bytesProcessed:p.bytesProcessed,totalBytes:p.totalBytes});return;case "sha256-done":e.signal.removeEventListener("abort",i),n(()=>r(p.sha256));return;case "error":{if(e.signal.removeEventListener("abort",i),p.error.cancelled)n(()=>t(A(e.signal)));else {let y=new Error(p.error.message);y.name=p.error.name,n(()=>t(y));}return}default:{let y=p;n(()=>t(new Error(`Unknown sha256-worker message: ${JSON.stringify(y)}`)));}}};s.addEventListener("message",v),s.addEventListener("error",l),s.addEventListener("messageerror",h);let w={type:"start",file:e.file};try{s.postMessage(w);}catch(f){n(()=>t(f instanceof Error?f:new Error(String(f))));}})}function fe(e,r,t){let s=Number.isFinite(t.workerPoolSize)&&t.workerPoolSize>=1?Math.floor(t.workerPoolSize):1,o=Math.max(1,Math.min(s,Math.max(1,r)));return new Promise((n,i)=>{let l=[],h=[],v=new Set,w=0,f=false;for(let u=1;u<=r;u++)h.push(u);let p=u=>{if(!f){f=true;for(let a of l){try{let m={type:"abort"};a.worker.postMessage(m);}catch{}try{a.worker.terminate();}catch{}}t.signal.removeEventListener("abort",y),u();}},y=()=>p(()=>i(A(t.signal)));if(t.signal.aborted){y();return}t.signal.addEventListener("abort",y,{once:true});let S=u=>{if(f)return;let a=h.shift();if(a===void 0){u.busyPart=null,w>=r&&l.every(E=>E.busyPart===null)&&p(()=>n());return}u.busyPart=a;let m=(a-1)*t.chunkSize,b=Math.min(m+t.chunkSize,t.file.size),k=t.file.slice(m,b),R={type:"put",apiBase:t.apiBase,authToken:t.authToken,sessionId:e,partNumber:a,contentRange:{start:m,end:b,total:t.file.size},blob:k,retries:{maxRetries:t.retries}};try{u.worker.postMessage(R);}catch(E){p(()=>i(E instanceof Error?E:new Error(String(E))));}},M=(u,a)=>{switch(a.type){case "put-done":w++,t.onChunkComplete({partNumber:a.partNumber,bytesUploaded:a.bytesUploaded,elapsedMs:a.elapsedMs}),S(u);return;case "error":{if(a.error.cancelled){p(()=>i(A(t.signal)));return}if(a.error.retryable&&!v.has(a.partNumber)&&l.length>1){v.add(a.partNumber),h.push(a.partNumber),z(u);for(let b of l.filter(k=>k.busyPart===null))S(b);return}let m=a.error.status!==void 0?new P(a.error.status,"",a.error.message):Object.assign(new Error(a.error.message),{name:a.error.name});p(()=>i(m));return}default:{let m=a;p(()=>i(new Error(`Unknown chunk-put-worker message: ${JSON.stringify(m)}`)));}}};for(let u=0;u<o;u++){let a=new Worker(new URL("./chunk-put-worker.js",import.meta.url),{type:"module"}),m={worker:a,index:u,busyPart:null};l.push(m),a.addEventListener("message",b=>M(m,b.data)),a.addEventListener("error",b=>p(()=>i(new Error(`Chunk PUT Worker[${u}] error: ${b.message??"(no message)"}`)))),a.addEventListener("messageerror",b=>p(()=>i(new Error(`Chunk PUT Worker[${u}] messageerror: ${String(b.data)}`)))),S(m);}let z=u=>{let a=l.indexOf(u);a>=0&&l.splice(a,1),u.busyPart=null;try{let m={type:"abort"};u.worker.postMessage(m);}catch{}try{u.worker.terminate();}catch{}};})}function A(e){return e.reason instanceof Error?e.reason:new DOMException("Aborted","AbortError")}var te={maxRetries:3,initialDelayMs:100,backoffMultiplier:2,maxDelayMs:5e3,jitterRatio:.25};async function L(e,r,t){let s={...te,...r},o;for(let n=0;n<=s.maxRetries;n++){if(t.aborted)throw t.reason instanceof Error?t.reason:new DOMException("Aborted","AbortError");try{return await e()}catch(i){if(o=i,i instanceof Error&&i.name==="AbortError"||i instanceof P&&!i.retryable)throw i;if(n===s.maxRetries)break;let l=Math.min(s.initialDelayMs*Math.pow(s.backoffMultiplier,n),s.maxDelayMs),h=l*s.jitterRatio*(Math.random()*2-1),v=Math.max(0,Math.round(l+h));await pe(v,t);}}throw o}function pe(e,r){return new Promise((t,s)=>{if(r.aborted){s(r.reason instanceof Error?r.reason:new DOMException("Aborted","AbortError"));return}let o=setTimeout(()=>{r.removeEventListener("abort",n),t();},e),n=()=>{clearTimeout(o),r.removeEventListener("abort",n),s(r.reason instanceof Error?r.reason:new DOMException("Aborted","AbortError"));};r.addEventListener("abort",n,{once:true});})}async function se(e){for(let r=1;r<=e.totalParts;r++){if(e.signal.aborted)throw e.signal.reason instanceof Error?e.signal.reason:new DOMException("Aborted","AbortError");let t=(r-1)*e.chunkSize,s=Math.min(t+e.chunkSize,e.file.size);if(e.skipParts?.has(r))continue;let o=e.file.slice(t,s),n=performance.now();await L(()=>e.transport.uploadChunk(e.sessionId,r,{start:t,end:s,total:e.file.size},o,e.signal),e.retries,e.signal);let i=performance.now()-n;e.onChunkComplete({partNumber:r,bytesUploaded:s-t,elapsedMs:i});}}async function ne(e){if(e.size>524288e3)throw new Error(`file too large for main-thread SHA-256 (${me(e.size)} > 500MB). Use Web Worker streaming SHA-256 (P0 #5 track) \u2014 not yet implemented in SDK v0.1.`);let t=await e.arrayBuffer(),s=await crypto.subtle.digest("SHA-256",t);return [...new Uint8Array(s)].map(o=>o.toString(16).padStart(2,"0")).join("")}function me(e){if(e<1024)return `${e} B`;let r=["KB","MB","GB"],t=e/1024,s=0;for(;t>=1024&&s<r.length-1;)t/=1024,s++;return `${t.toFixed(1)} ${r[s]}`}var D=class{sha256;constructor(r){this.sha256=r;}async compute(){return this.sha256}},H=class{compute(r){return ne(r)}};function oe(e){return e===void 0?new H:new D(e)}var I=class{opts;constructor(r){this.opts=r;}async run(){let r=performance.now(),t=await this.opts.hashStrategy.compute(this.opts.file),s,o;if(this.opts.resumeSessionId!==void 0){o=await this.opts.transport.getSession(this.opts.resumeSessionId,this.opts.signal),ge(o,{file:this.opts.file,chunkSize:this.opts.chunkSize,totalParts:this.opts.totalParts,sha256:t});let h=await this.opts.transport.getProgress(this.opts.resumeSessionId,this.opts.signal);he(h,this.opts.resumeSessionId),s=new Set(h.completedParts),this.opts.onResumeProgress(ye(s,this.opts.file.size,this.opts.chunkSize));}else o=await this.opts.transport.createSession({fileName:this.opts.file.name,totalBytes:this.opts.file.size,totalParts:this.opts.totalParts,sha256:t,chunkSize:this.opts.chunkSize,storageProfile:this.opts.storageProfile},this.opts.signal);if(this.opts.onSessionCreated(o),await se({transport:this.opts.transport,sessionId:o.sessionId,file:this.opts.file,chunkSize:this.opts.chunkSize,totalParts:this.opts.totalParts,retries:{maxRetries:this.opts.retries},signal:this.opts.signal,skipParts:s,onChunkComplete:this.opts.onChunkComplete}),this.opts.signal.aborted)throw this.opts.signal.reason instanceof Error?this.opts.signal.reason:new DOMException("Aborted","AbortError");let n=await this.opts.transport.commitSession(o.sessionId,this.opts.signal),i=performance.now()-r,l=this.opts.file.size/(1024*1024)/(i/1e3);return {finalSession:n,totalElapsedMs:i,averageMbps:l}}};function ge(e,r){if(e.totalBytes!==r.file.size)throw new Error(`resume session file size mismatch: session=${e.totalBytes}, file=${r.file.size}`);if(e.chunkSize!==r.chunkSize)throw new Error(`resume session chunk size mismatch: session=${e.chunkSize}, requested=${r.chunkSize}`);if(e.totalParts!==r.totalParts)throw new Error(`resume session total parts mismatch: session=${e.totalParts}, requested=${r.totalParts}`);if(e.sha256.toLowerCase()!==r.sha256.toLowerCase())throw new Error("resume session SHA-256 mismatch");if(e.state==="COMMITTED")throw new Error("resume session is already committed");if(e.state==="ABORTED"||e.state==="FAILED")throw new Error(`resume session is terminal: ${e.state}`)}function he(e,r){if(e.sessionId!==r)throw new Error(`resume progress session mismatch: expected ${r}, got ${e.sessionId}`)}function ye(e,r,t){let s=0;for(let o of e){if(o<1)continue;let n=(o-1)*t;if(n>=r)continue;let i=Math.min(n+t,r);s+=i-n;}return Math.min(s,r)}var O=class{apiBase;authToken;constructor(r,t){this.apiBase=r,this.authToken=t;}createSession(r,t){return Y(this.apiBase,r,t,this.authToken)}getSession(r,t){return J(this.apiBase,r,t,this.authToken)}getProgress(r,t){return V(this.apiBase,r,t,this.authToken)}uploadChunk(r,t,s,o,n){return Z(this.apiBase,r,t,s,o,n,this.authToken)}commitSession(r,t){return Q(this.apiBase,r,t,this.authToken)}abortSession(r,t){return X(this.apiBase,r,t,this.authToken)}};var B=class{opts;constructor(r){this.opts=r;}run(){return re(this.opts)}};var Se=8*1024*1024,be=3,ke=1;function Ee(e){let r=e.apiBase??`${location.origin}/api/v1/sessions`,t=e.authToken,s=e.chunkSize??Se,o=e.storageProfile,n=e.retries??be,i=e.workerPoolSize??ke,l=e.file,h=Math.ceil(l.size/s),v=e.resumeSessionId,w=new O(r,t),f=new AbortController,p=e.signal?Pe(e.signal,f.signal):f.signal,y=false,S=new U,M,z,u=new Promise((d,c)=>{M=d,z=c;}),a,m,b=new Promise((d,c)=>{a=d,m=c;}),k=0,R=performance.now(),E,N=d=>{k+=d.bytesUploaded;let c=performance.now(),g=Math.max(.001,(c-R)/1e3),W=d.bytesUploaded/(1024*1024)/g;R=c,S.emit("chunk:done",{partNumber:d.partNumber,totalParts:h,bytesUploaded:d.bytesUploaded,elapsedMs:d.elapsedMs});let ae=l.size>0?k/l.size*100:100,le=Math.max(0,l.size-k),ue=W>0?le/(W*1024*1024):0,de={bytesSent:k,totalBytes:l.size,percent:ae,mbps:W,etaSeconds:ue};S.emit("progress",de);},ie=v===void 0&&e.forceMainThread!==true&&e.sha256===void 0&&$();return (async()=>{try{let c=await(ie?new B({apiBase:r,transport:w,authToken:t,file:l,chunkSize:s,storageProfile:o,retries:n,workerPoolSize:i,signal:p,onSha256Progress:g=>{S.emit("sha256:progress",{bytesProcessed:g.bytesProcessed,totalBytes:g.totalBytes,percent:g.totalBytes>0?g.bytesProcessed/g.totalBytes*100:0});},onSessionCreated:g=>{E=g.sessionId,M(g.sessionId);},onChunkComplete:N}):new I({transport:w,hashStrategy:oe(e.sha256),file:l,chunkSize:s,totalParts:h,storageProfile:o,retries:n,signal:p,resumeSessionId:v,onSessionCreated:g=>{E=g.sessionId,M(g.sessionId);},onResumeProgress:g=>{k=g,R=performance.now(),S.emit("progress",{bytesSent:k,totalBytes:l.size,percent:l.size>0?k/l.size*100:0,mbps:0,etaSeconds:0});},onChunkComplete:N})).run();S.emit("session:complete",{session:c.finalSession,totalElapsedMs:c.totalElapsedMs,averageMbps:c.averageMbps}),a(c.finalSession);}catch(d){let c=d instanceof Error?d:new Error(String(d)),g=y||c.name==="AbortError"||c instanceof P&&c.status===0&&p.aborted;S.emit("session:error",{error:c,cancelled:g}),E===void 0&&z(c),m(c);}})(),{sessionId:u,done:b,on:(d,c)=>S.on(d,c),once:(d,c)=>S.once(d,c),abort:async()=>{if(!y&&(y=true,f.abort(),E!==void 0))try{let d=new AbortController;await w.abortSession(E,d.signal);}catch(d){console.warn("[transfer-sdk] abort DELETE failed (non-critical):",d);}}}}function Pe(...e){if(typeof AbortSignal.any=="function")return AbortSignal.any(e);let r=new AbortController;for(let t of e){if(t.aborted)return r.abort(t.reason),r.signal;t.addEventListener("abort",()=>r.abort(t.reason),{once:true});}return r.signal}async function ve(e={}){let r=e.signal===void 0?new AbortController:void 0,t=e.signal??r?.signal;if(t===void 0)throw new Error("AbortSignal unavailable");return ee(e.apiRoot??we(),t,e.authToken)}function we(){let e=globalThis.location;return e===void 0?"/api/v1":`${e.origin}/api/v1`}var Xe="0.1.1";export{P as ApiError,te as DEFAULT_RETRY_OPTIONS,U as EventEmitter,Xe as VERSION,Ee as createTransferSession,ve as listStorageProfiles,L as retryWithBackoff};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
'use strict';function W(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function y(e,...t){if(!W(e))throw new Error("Uint8Array expected");if(t.length>0&&!t.includes(e.length))throw new Error("Uint8Array expected of length "+t+", got length="+e.length)}function L(e,t=true){if(e.destroyed)throw new Error("Hash instance has been destroyed");if(t&&e.finished)throw new Error("Hash#digest() has already been called")}function _(e,t){y(e);let s=t.outputLen;if(e.length<s)throw new Error("digestInto() expects output buffer of length at least "+s)}function g(...e){for(let t=0;t<e.length;t++)e[t].fill(0);}function H(e){return new DataView(e.buffer,e.byteOffset,e.byteLength)}function x(e,t){return e<<32-t|e>>>t}var M=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",O=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function D(e){if(y(e),M)return e.toHex();let t="";for(let s=0;s<e.length;s++)t+=O[e[s]];return t}function j(e){if(typeof e!="string")throw new Error("string expected");return new Uint8Array(new TextEncoder().encode(e))}function U(e){return typeof e=="string"&&(e=j(e)),y(e),e}var m=class{};function F(e){let t=r=>e().update(U(r)).digest(),s=e();return t.outputLen=s.outputLen,t.blockLen=s.blockLen,t.create=()=>e(),t}function v(e,t,s,r){if(typeof e.setBigUint64=="function")return e.setBigUint64(t,s,r);let n=BigInt(32),c=BigInt(4294967295),o=Number(s>>n&c),i=Number(s&c),h=r?4:0,f=r?0:4;e.setUint32(t+h,o,r),e.setUint32(t+f,i,r);}function I(e,t,s){return e&t^~e&s}function G(e,t,s){return e&t^e&s^t&s}var B=class extends m{constructor(t,s,r,n){super(),this.finished=false,this.length=0,this.pos=0,this.destroyed=false,this.blockLen=t,this.outputLen=s,this.padOffset=r,this.isLE=n,this.buffer=new Uint8Array(t),this.view=H(this.buffer);}update(t){L(this),t=U(t),y(t);let{view:s,buffer:r,blockLen:n}=this,c=t.length;for(let o=0;o<c;){let i=Math.min(n-this.pos,c-o);if(i===n){let h=H(t);for(;n<=c-o;o+=n)this.process(h,o);continue}r.set(t.subarray(o,o+i),this.pos),this.pos+=i,o+=i,this.pos===n&&(this.process(s,0),this.pos=0);}return this.length+=t.length,this.roundClean(),this}digestInto(t){L(this),_(t,this),this.finished=true;let{buffer:s,view:r,blockLen:n,isLE:c}=this,{pos:o}=this;s[o++]=128,g(this.buffer.subarray(o)),this.padOffset>n-o&&(this.process(r,0),o=0);for(let a=o;a<n;a++)s[a]=0;v(r,n-8,BigInt(this.length*8),c),this.process(r,0);let i=H(t),h=this.outputLen;if(h%4)throw new Error("_sha2: outputLen should be aligned to 32bit");let f=h/4,l=this.get();if(f>l.length)throw new Error("_sha2: outputLen bigger than state");for(let a=0;a<f;a++)i.setUint32(4*a,l[a],c);}digest(){let{buffer:t,outputLen:s}=this;this.digestInto(t);let r=t.slice(0,s);return this.destroy(),r}_cloneInto(t){t||(t=new this.constructor),t.set(...this.get());let{blockLen:s,buffer:r,length:n,finished:c,destroyed:o,pos:i}=this;return t.destroyed=o,t.finished=c,t.length=n,t.pos=i,n%s&&t.buffer.set(r),t}clone(){return this._cloneInto()}},d=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]);var P=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),b=new Uint32Array(64),E=class extends B{constructor(t=32){super(64,t,8,false),this.A=d[0]|0,this.B=d[1]|0,this.C=d[2]|0,this.D=d[3]|0,this.E=d[4]|0,this.F=d[5]|0,this.G=d[6]|0,this.H=d[7]|0;}get(){let{A:t,B:s,C:r,D:n,E:c,F:o,G:i,H:h}=this;return [t,s,r,n,c,o,i,h]}set(t,s,r,n,c,o,i,h){this.A=t|0,this.B=s|0,this.C=r|0,this.D=n|0,this.E=c|0,this.F=o|0,this.G=i|0,this.H=h|0;}process(t,s){for(let a=0;a<16;a++,s+=4)b[a]=t.getUint32(s,false);for(let a=16;a<64;a++){let p=b[a-15],u=b[a-2],C=x(p,7)^x(p,18)^p>>>3,S=x(u,17)^x(u,19)^u>>>10;b[a]=S+b[a-7]+C+b[a-16]|0;}let{A:r,B:n,C:c,D:o,E:i,F:h,G:f,H:l}=this;for(let a=0;a<64;a++){let p=x(i,6)^x(i,11)^x(i,25),u=l+p+I(i,h,f)+P[a]+b[a]|0,S=(x(r,2)^x(r,13)^x(r,22))+G(r,n,c)|0;l=f,f=h,h=i,i=o+u|0,o=c,c=n,n=r,r=u+S|0;}r=r+this.A|0,n=n+this.B|0,c=c+this.C|0,o=o+this.D|0,i=i+this.E|0,h=h+this.F|0,f=f+this.G|0,l=l+this.H|0,this.set(r,n,c,o,i,h,f,l);}roundClean(){g(b);}destroy(){this.set(0,0,0,0,0,0,0,0),g(this.buffer);}};var k=F(()=>new E);var V=k;var A=null,T=self;T.addEventListener("message",e=>{let t=e.data;if(t.type==="abort"){A?.abort();return}if(t.type==="start"){if(A!==null)return;A=new AbortController,z(t.file).catch(s=>{let r=s instanceof Error?s:new Error(String(s)),n=A?.signal,c=r.name==="AbortError"||n?.aborted===true;w({type:"error",error:{name:r.name,message:r.message,cancelled:c}});});}});async function z(e){let t=A.signal,s=V.create(),r=e.stream().getReader(),n=0,c=0;try{for(w({type:"sha256-progress",bytesProcessed:0,totalBytes:e.size});;){if(t.aborted)throw await r.cancel(),new DOMException("Aborted","AbortError");let{done:i,value:h}=await r.read();if(i)break;s.update(h),n+=h.byteLength;let f=performance.now();f-c>100&&(w({type:"sha256-progress",bytesProcessed:n,totalBytes:e.size}),c=f);}w({type:"sha256-progress",bytesProcessed:n,totalBytes:e.size});}finally{try{r.releaseLock();}catch{}}let o=D(s.digest());w({type:"sha256-done",sha256:o,totalBytes:e.size});}function w(e){T.postMessage(e);}
|
|
2
|
+
/*! Bundled license information:
|
|
3
|
+
|
|
4
|
+
@noble/hashes/esm/utils.js:
|
|
5
|
+
(*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
6
|
+
*/
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
function W(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array"}function y(e,...t){if(!W(e))throw new Error("Uint8Array expected");if(t.length>0&&!t.includes(e.length))throw new Error("Uint8Array expected of length "+t+", got length="+e.length)}function L(e,t=true){if(e.destroyed)throw new Error("Hash instance has been destroyed");if(t&&e.finished)throw new Error("Hash#digest() has already been called")}function _(e,t){y(e);let s=t.outputLen;if(e.length<s)throw new Error("digestInto() expects output buffer of length at least "+s)}function g(...e){for(let t=0;t<e.length;t++)e[t].fill(0);}function H(e){return new DataView(e.buffer,e.byteOffset,e.byteLength)}function x(e,t){return e<<32-t|e>>>t}var M=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",O=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,"0"));function D(e){if(y(e),M)return e.toHex();let t="";for(let s=0;s<e.length;s++)t+=O[e[s]];return t}function j(e){if(typeof e!="string")throw new Error("string expected");return new Uint8Array(new TextEncoder().encode(e))}function U(e){return typeof e=="string"&&(e=j(e)),y(e),e}var m=class{};function F(e){let t=r=>e().update(U(r)).digest(),s=e();return t.outputLen=s.outputLen,t.blockLen=s.blockLen,t.create=()=>e(),t}function v(e,t,s,r){if(typeof e.setBigUint64=="function")return e.setBigUint64(t,s,r);let n=BigInt(32),c=BigInt(4294967295),o=Number(s>>n&c),i=Number(s&c),h=r?4:0,f=r?0:4;e.setUint32(t+h,o,r),e.setUint32(t+f,i,r);}function I(e,t,s){return e&t^~e&s}function G(e,t,s){return e&t^e&s^t&s}var B=class extends m{constructor(t,s,r,n){super(),this.finished=false,this.length=0,this.pos=0,this.destroyed=false,this.blockLen=t,this.outputLen=s,this.padOffset=r,this.isLE=n,this.buffer=new Uint8Array(t),this.view=H(this.buffer);}update(t){L(this),t=U(t),y(t);let{view:s,buffer:r,blockLen:n}=this,c=t.length;for(let o=0;o<c;){let i=Math.min(n-this.pos,c-o);if(i===n){let h=H(t);for(;n<=c-o;o+=n)this.process(h,o);continue}r.set(t.subarray(o,o+i),this.pos),this.pos+=i,o+=i,this.pos===n&&(this.process(s,0),this.pos=0);}return this.length+=t.length,this.roundClean(),this}digestInto(t){L(this),_(t,this),this.finished=true;let{buffer:s,view:r,blockLen:n,isLE:c}=this,{pos:o}=this;s[o++]=128,g(this.buffer.subarray(o)),this.padOffset>n-o&&(this.process(r,0),o=0);for(let a=o;a<n;a++)s[a]=0;v(r,n-8,BigInt(this.length*8),c),this.process(r,0);let i=H(t),h=this.outputLen;if(h%4)throw new Error("_sha2: outputLen should be aligned to 32bit");let f=h/4,l=this.get();if(f>l.length)throw new Error("_sha2: outputLen bigger than state");for(let a=0;a<f;a++)i.setUint32(4*a,l[a],c);}digest(){let{buffer:t,outputLen:s}=this;this.digestInto(t);let r=t.slice(0,s);return this.destroy(),r}_cloneInto(t){t||(t=new this.constructor),t.set(...this.get());let{blockLen:s,buffer:r,length:n,finished:c,destroyed:o,pos:i}=this;return t.destroyed=o,t.finished=c,t.length=n,t.pos=i,n%s&&t.buffer.set(r),t}clone(){return this._cloneInto()}},d=Uint32Array.from([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]);var P=Uint32Array.from([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),b=new Uint32Array(64),E=class extends B{constructor(t=32){super(64,t,8,false),this.A=d[0]|0,this.B=d[1]|0,this.C=d[2]|0,this.D=d[3]|0,this.E=d[4]|0,this.F=d[5]|0,this.G=d[6]|0,this.H=d[7]|0;}get(){let{A:t,B:s,C:r,D:n,E:c,F:o,G:i,H:h}=this;return [t,s,r,n,c,o,i,h]}set(t,s,r,n,c,o,i,h){this.A=t|0,this.B=s|0,this.C=r|0,this.D=n|0,this.E=c|0,this.F=o|0,this.G=i|0,this.H=h|0;}process(t,s){for(let a=0;a<16;a++,s+=4)b[a]=t.getUint32(s,false);for(let a=16;a<64;a++){let p=b[a-15],u=b[a-2],C=x(p,7)^x(p,18)^p>>>3,S=x(u,17)^x(u,19)^u>>>10;b[a]=S+b[a-7]+C+b[a-16]|0;}let{A:r,B:n,C:c,D:o,E:i,F:h,G:f,H:l}=this;for(let a=0;a<64;a++){let p=x(i,6)^x(i,11)^x(i,25),u=l+p+I(i,h,f)+P[a]+b[a]|0,S=(x(r,2)^x(r,13)^x(r,22))+G(r,n,c)|0;l=f,f=h,h=i,i=o+u|0,o=c,c=n,n=r,r=u+S|0;}r=r+this.A|0,n=n+this.B|0,c=c+this.C|0,o=o+this.D|0,i=i+this.E|0,h=h+this.F|0,f=f+this.G|0,l=l+this.H|0,this.set(r,n,c,o,i,h,f,l);}roundClean(){g(b);}destroy(){this.set(0,0,0,0,0,0,0,0),g(this.buffer);}};var k=F(()=>new E);var V=k;var A=null,T=self;T.addEventListener("message",e=>{let t=e.data;if(t.type==="abort"){A?.abort();return}if(t.type==="start"){if(A!==null)return;A=new AbortController,z(t.file).catch(s=>{let r=s instanceof Error?s:new Error(String(s)),n=A?.signal,c=r.name==="AbortError"||n?.aborted===true;w({type:"error",error:{name:r.name,message:r.message,cancelled:c}});});}});async function z(e){let t=A.signal,s=V.create(),r=e.stream().getReader(),n=0,c=0;try{for(w({type:"sha256-progress",bytesProcessed:0,totalBytes:e.size});;){if(t.aborted)throw await r.cancel(),new DOMException("Aborted","AbortError");let{done:i,value:h}=await r.read();if(i)break;s.update(h),n+=h.byteLength;let f=performance.now();f-c>100&&(w({type:"sha256-progress",bytesProcessed:n,totalBytes:e.size}),c=f);}w({type:"sha256-progress",bytesProcessed:n,totalBytes:e.size});}finally{try{r.releaseLock();}catch{}}let o=D(s.digest());w({type:"sha256-done",sha256:o,totalBytes:e.size});}function w(e){T.postMessage(e);}
|
|
2
|
+
/*! Bundled license information:
|
|
3
|
+
|
|
4
|
+
@noble/hashes/esm/utils.js:
|
|
5
|
+
(*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
6
|
+
*/
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rebalworks/transfer-sdk",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Browser file-transfer SDK for rebalTransfer",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"private": false,
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"dev": "tsup --watch",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"lint": "echo 'lint not configured'",
|
|
31
|
+
"test": "pnpm build && node --test test/*.test.mjs",
|
|
32
|
+
"size-limit": "size-limit",
|
|
33
|
+
"clean": "rimraf dist .tsbuildinfo"
|
|
34
|
+
},
|
|
35
|
+
"size-limit": [
|
|
36
|
+
{
|
|
37
|
+
"name": "core (gzipped, ESM)",
|
|
38
|
+
"path": "dist/index.js",
|
|
39
|
+
"limit": "35 KB",
|
|
40
|
+
"gzip": true
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "worker — sha256 (gzipped, ESM)",
|
|
44
|
+
"path": "dist/sha256-worker.js",
|
|
45
|
+
"limit": "25 KB",
|
|
46
|
+
"gzip": true
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "worker — chunk-put (gzipped, ESM)",
|
|
50
|
+
"path": "dist/chunk-put-worker.js",
|
|
51
|
+
"limit": "10 KB",
|
|
52
|
+
"gzip": true
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@noble/hashes": "^1.5.0",
|
|
57
|
+
"@size-limit/preset-small-lib": "^11.1.0",
|
|
58
|
+
"size-limit": "^11.1.0",
|
|
59
|
+
"tsup": "^8.3.0",
|
|
60
|
+
"typescript": "^5.5.0"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=20"
|
|
64
|
+
}
|
|
65
|
+
}
|