aspect-sync 0.1.31 → 0.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -8
- package/dist/index.js +26 -20
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -14,6 +14,12 @@ npm install -g aspect-sync
|
|
|
14
14
|
aspect-sync --help
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
Log in once per runner to store Aspect destination credentials:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
aspect-sync login
|
|
21
|
+
```
|
|
22
|
+
|
|
17
23
|
Sync commands:
|
|
18
24
|
|
|
19
25
|
```bash
|
|
@@ -36,6 +42,8 @@ Shared Aspect destination options:
|
|
|
36
42
|
--upload-concurrent <number>
|
|
37
43
|
```
|
|
38
44
|
|
|
45
|
+
`--asp-api-key` is optional after login. Sync commands resolve the key from the flag first, then `ASPECT_API_KEY`, then `~/.config/aspect-sync/aspect-auth.json`.
|
|
46
|
+
|
|
39
47
|
Rclone example:
|
|
40
48
|
|
|
41
49
|
```bash
|
|
@@ -43,8 +51,7 @@ aspect-sync sync rclone \
|
|
|
43
51
|
--remote dropbox \
|
|
44
52
|
--source-path /Customer/Folder \
|
|
45
53
|
--asp-directory-id <aspect-directory-id> \
|
|
46
|
-
--asp-project-id <aspect-project-id>
|
|
47
|
-
--asp-api-key <aspect-api-key>
|
|
54
|
+
--asp-project-id <aspect-project-id>
|
|
48
55
|
```
|
|
49
56
|
|
|
50
57
|
Local example:
|
|
@@ -53,8 +60,7 @@ Local example:
|
|
|
53
60
|
aspect-sync sync local \
|
|
54
61
|
--source-path /data/customer-files \
|
|
55
62
|
--asp-directory-id <aspect-directory-id> \
|
|
56
|
-
--asp-project-id <aspect-project-id>
|
|
57
|
-
--asp-api-key <aspect-api-key>
|
|
63
|
+
--asp-project-id <aspect-project-id>
|
|
58
64
|
```
|
|
59
65
|
|
|
60
66
|
LucidLink example:
|
|
@@ -67,8 +73,7 @@ aspect-sync sync lucidlink \
|
|
|
67
73
|
--lucid-instance 9001 \
|
|
68
74
|
--lucid-cache-size 500GB \
|
|
69
75
|
--asp-directory-id <aspect-directory-id> \
|
|
70
|
-
--asp-project-id <aspect-project-id>
|
|
71
|
-
--asp-api-key <aspect-api-key>
|
|
76
|
+
--asp-project-id <aspect-project-id>
|
|
72
77
|
```
|
|
73
78
|
|
|
74
79
|
Frame.io example:
|
|
@@ -80,8 +85,7 @@ aspect-sync sync frameio \
|
|
|
80
85
|
--source-folder-id <frameio-folder-id> \
|
|
81
86
|
--frameio-download-concurrent 8 \
|
|
82
87
|
--asp-directory-id <aspect-directory-id> \
|
|
83
|
-
--asp-project-id <aspect-project-id>
|
|
84
|
-
--asp-api-key <aspect-api-key>
|
|
88
|
+
--asp-project-id <aspect-project-id>
|
|
85
89
|
```
|
|
86
90
|
|
|
87
91
|
Source helpers:
|
package/dist/index.js
CHANGED
|
@@ -1,28 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as ci}from"commander";import Bn from"node:path";import{readFileSync as ui,realpathSync as On}from"node:fs";import{fileURLToPath as di}from"node:url";import ue from"node:fs/promises";import wt from"node:path";import $n from"fs/promises";import Gn from"path";function Ot(n,e){let t=new Map;for(let c of n){let u=Gn.dirname(c.targetPath??c.path);t.has(u)||t.set(u,[]),t.get(u).push(c)}let r=new Map;for(let[c,u]of t.entries()){let d=u.reduce((m,g)=>m+g.size,0);r.set(c,d)}let s=Array.from(t.keys()).sort(),i=[],o=[],a=0,l=1;for(let c of s){let u=t.get(c),d=r.get(c);if(d>e){if(o.length>0&&(i.push({batchNumber:l++,files:o,totalSize:a}),o=[],a=0),u.length===1)i.push({batchNumber:l++,files:u,totalSize:d});else for(let m of u)a+m.size>e&&o.length>0&&(i.push({batchNumber:l++,files:o,totalSize:a}),o=[],a=0),o.push(m),a+=m.size;continue}a+d>e&&o.length>0&&(i.push({batchNumber:l++,files:o,totalSize:a}),o=[],a=0),o.push(...u),a+=d}return o.length>0&&i.push({batchNumber:l++,files:o,totalSize:a}),i}async function Bt(n){try{await $n.unlink(n)}catch(e){if(e.code!=="ENOENT")throw e}}import f from"chalk";import Nt from"log-update";function be(n,e){if(e.length===0)return n.finalizedStatus?n.finalizedStatus:n.isCreatingFolders?"creating-folders":"queued";if(n.isCreatingFolders)return"creating-folders";let t={queued:0,paused:0,inProgress:0,success:0,failed:0,cancelled:0};for(let s of e)switch(s.status){case"queued":t.queued++;break;case"paused":t.paused++;break;case"in-progress":t.inProgress++;break;case"success":t.success++;break;case"failed":t.failed++;break;case"cancelled":t.cancelled++;break}let r=e.length;return t.failed===r?"all-failed":t.failed>0?"some-failed":t.success===r?"success":t.paused>0&&t.queued===0&&t.inProgress===0?"paused":t.queued>0||t.inProgress>0?t.queued+t.paused===r?"queued":"in-progress":"cancelled"}function et(n,e){let t=be(n,e);return t==="creating-folders"||t==="in-progress"||t==="queued"||t==="paused"?"cancelled":t}function tt(n){let e=[];for(let t of Object.values(n))t.chunkedState&&(t.status==="queued"||t.status==="in-progress"||t.status==="paused")&&e.push(t.chunkedState.assetId);return e}function nt(n){for(let e of Object.values(n))if(e.status==="queued"||e.status==="in-progress"||e.status==="paused")return!0;return!1}function Z(n){let t=Object.values(n).reduce((r,s)=>{switch(s.status!=="failed"&&s.status!=="cancelled"&&(r.totalBytesToUpload+=s.totalBytesToUpload,r.totalBytesUploaded+=s.bytesUploaded),r.totalAssetCount+=1,s.status){case"queued":r.queuedAssetCount+=1;break;case"paused":r.pausedAssetCount+=1;break;case"in-progress":r.inProgressAssetCount+=1;break;case"success":r.successAssetCount+=1;break;case"failed":r.failedAssetCount+=1;break;case"cancelled":r.cancelledAssetCount+=1;break}return r},{totalBytesToUpload:0,totalBytesUploaded:0,totalAssetCount:0,queuedAssetCount:0,pausedAssetCount:0,inProgressAssetCount:0,successAssetCount:0,failedAssetCount:0,cancelledAssetCount:0,hasActiveUploads:!1,progress:0});return t.hasActiveUploads=t.totalAssetCount-t.successAssetCount-t.failedAssetCount-t.cancelledAssetCount>0,t.progress=t.hasActiveUploads?t.totalBytesUploaded/t.totalBytesToUpload:0,t}function rt(n,e){if(e.length===0)return null;let t=e.reduce((r,s)=>(s.status!=="failed"&&s.status!=="cancelled"&&(r.totalBytes+=s.totalBytesToUpload,r.uploadedBytes+=s.bytesUploaded),s.status==="success"?r.filesSucceeded++:s.status==="failed"&&r.filesFailed++,(s.status==="success"||s.status==="failed"||s.status==="cancelled")&&r.filesCompleted++,r),{totalBytes:0,uploadedBytes:0,filesCompleted:0,filesSucceeded:0,filesTotal:e.length,filesFailed:0,percentage:0});return t.percentage=t.totalBytes>0?t.uploadedBytes/t.totalBytes*100:0,t}function st(n){let e=Object.values(n).filter(t=>t.status==="queued"||t.status==="in-progress"||t.status==="paused");return e.length===0?!1:e.every(t=>t.status==="paused")}function it(n){return Object.values(n).some(e=>e.status==="paused")}import ki from"axios";var ee=class{#e;#n;#t;#r;#s;#i=0;#a=0;#c=0;#o=0;#u=0;#p=0;constructor(e){this.#e=e?.alphaFast??.1,this.#n=e?.alphaMax??.5,this.#t=e?.consecutiveForBoost??3,this.#r=e?.minSamples??3,this.#s=e?.maxGapSeconds??2}sample(e){let t=Date.now();if(this.#o===0){this.#o=t,this.#u=e;return}let s=(t-this.#o)/1e3,i=e-this.#u;if(s<=0||i<0)return;if(s>this.#s){this.#o=t,this.#u=e;return}let o=i/s;if(this.#p===0)this.#i=o;else{let l=o-this.#i>=0?1:-1;this.#c!==0&&l===this.#c?this.#a++:this.#a=0,this.#c=l;let c=Math.min(1,this.#a/this.#t),u=this.#e+(this.#n-this.#e)*c;this.#i=u*o+(1-u)*this.#i}this.#o=t,this.#u=e,this.#p++}etaSeconds(e){return!this.isWarmedUp||this.#i<=0?0:e/this.#i}adjustTotalBytes(e){this.#u+=e}reset(){this.#i=0,this.#a=0,this.#c=0,this.#o=0,this.#u=0,this.#p=0}serialize(){return{displaySpeedBps:this.#i,lastSampleTimestamp:this.#o,lastSampleTotalBytes:this.#u,sampleCount:this.#p}}get speedBps(){return this.#i}get speedMbps(){return this.#i*8/1e6}get isWarmedUp(){return this.#p>=this.#r}};function D(n){let e={"X-Aspect-Share-Id":n.shareId};return n.shareAuthentication&&(e["X-Aspect-Share-Authentication"]=n.shareAuthentication),e}var te=class{#e;#n;#t;#r;#s;#i;#a;#c;#o;#u;#p;#l;#U;#y;#F;#k;#C;#b;#R;#P;#T;#m;#A;#I;#d;#v;#f;#w;#D;#B;#L;#O;constructor(e){this.#n=e?.minConcurrency??1,this.#t=e?.maxConcurrency??8,this.#e=this.#H(e?.initialConcurrency??this.#n),this.#r=e?.errorThreshold??1,this.#s=(e?.cooldownSeconds??10)*1e3,this.#i=e?.plateauThreshold??.05,this.#a=Math.max(this.#t,Math.floor(e?.sampleWindowSize??64)),this.#c=Math.max(2,Math.floor(e?.minSamples??4)),this.#o=Math.max(1.1,e?.increaseFactor??1.5),this.#u=e?.onChange,this.#p=e?.now??Date.now,this.#l=this.#e,this.#U=0,this.#y=[],this.#F=0,this.#k=0,this.#C=-1,this.#b=0,this.#R=void 0,this.#P=0,this.#T=0,this.#m=0,this.#A=this.#l,this.#I=0,this.#d=1/0,this.#v=0,this.#f=6e4,this.#w=0,this.#D=1/0,this.#B=0,this.#L=0,this.#O=0}recordSuccess(e,t,r){if(e<=0)return;if(r?.generation!==void 0){if(r.generation!==this.#U){r.generation===this.#C&&this.#b>0&&(this.#b--,this.#b===0&&(this.#R=r.completedAtMs??this.#p()));return}if(this.#b>0||this.#R!==void 0&&r.startedAtMs!==void 0&&r.startedAtMs<this.#R)return}else if(this.#k>0){this.#k--;return}let s=r?.completedAtMs??this.#p();for(this.#y.push({bytes:e,completedAtMs:s,startedAtMs:r?.startedAtMs,durationMs:t!==void 0&&t>0?t:void 0});this.#y.length>this.#a;)this.#y.shift();this.#F++,this.#P=0;let i=this.#N();this.#L=i.throughputBps,this.#O=i.latencyMsPerMB,this.#_(i)}recordError(){if(this.#P++,this.#P<this.#r)return;let e=this.#l;e===this.#w&&(this.#D=Math.min(this.#D,e),this.#B=this.#p()+3e4),this.#w=e;let t=this.#H(Math.floor(e/2));this.#T=this.#p()+this.#s,this.#P=0,e<=this.#A&&(this.#A=t,this.#I=0),e>t&&(this.#d=Math.min(this.#d,e),this.#W()),this.#g(t)}get concurrency(){return this.#l}get generation(){return this.#U}get speedBps(){return this.#L}get latencyMsPerMB(){return this.#O}reset(){this.#l=this.#e,this.#U++,this.#y=[],this.#F=0,this.#k=0,this.#C=-1,this.#b=0,this.#R=void 0,this.#P=0,this.#T=0,this.#m=0,this.#A=this.#l,this.#I=0,this.#d=1/0,this.#v=0,this.#f=6e4,this.#w=0,this.#D=1/0,this.#B=0,this.#L=0,this.#O=0,this.#u?.(this.#l)}#_(e){if(this.#y.length<this.#q()||this.#F<this.#q()||e.throughputBps<=0)return;let t=this.#p();if(t<this.#T)return;if(e.averageDurationMs>=2e4&&this.#l>=4){this.#A=Math.max(this.#n,Math.floor(this.#l/2)),this.#I=0,this.#g(this.#A);return}if(this.#I===0){this.#M(e.throughputBps),this.#x(e);return}let r=(e.throughputBps-this.#I)/this.#I;if(r>=this.#i){this.#M(e.throughputBps),this.#x(e);return}if(this.#l>this.#A){let s=r<=-.08,i=r<this.#i;(s||i)&&(this.#d=Math.min(this.#d,this.#l),this.#W(),this.#g(this.#A));return}if(this.#l<this.#A){this.#x(e);return}this.#l===this.#A&&(this.#I=Math.max(this.#I,e.throughputBps),t>=this.#m&&this.#x(e))}#x(e){let t=this.#V();if(this.#l>=t){this.#F=0;return}if(e.averageDurationMs>=5e3&&this.#l>=4&&this.#I>0){this.#F=0;return}if(this.#G()){let s=this.#p();if(this.#v===0){this.#v=s+this.#f,this.#m=this.#v,this.#F=0;return}if(s<this.#v){this.#F=0;return}}let r=this.#h(t);if(r===this.#l){this.#F=0;return}this.#g(r)}#M(e){this.#A=this.#l,this.#I=e,this.#d<=this.#l&&(this.#d=1/0),this.#v=0,this.#f=6e4,this.#m=0}#h(e){if(this.#d<1/0){let s=Math.floor((this.#l+this.#d)/2);return s>this.#l&&s<this.#d?Math.min(e,s):Math.min(e,this.#l+1)}if(this.#l<4)return Math.min(e,this.#l+1);let t=Math.ceil(this.#l*this.#o),r=this.#l+2;return Math.min(e,Math.max(r,t))}#g(e){let t=this.#l,r=this.#U,s=this.#H(e);s!==t&&(this.#E(),this.#l=s,this.#U++,this.#C=r,this.#b=Math.max(0,t-1),this.#R=this.#b===0?this.#p():void 0,this.#k=Math.max(0,t-1),this.#u?.(this.#l))}#E(){this.#y=[],this.#F=0,this.#k=0}#G(){return this.#d<1/0&&this.#l===this.#A&&this.#d<=this.#A+1}#W(){let e=this.#d<1/0&&this.#d<=this.#A+1,t=e?this.#f:1e4;this.#m=this.#p()+t,e&&(this.#v=this.#m,this.#f=Math.min(this.#f*2,3e5))}#q(){return Math.max(this.#c,this.#l)}#V(){return this.#D<1/0&&this.#p()>=this.#B&&(this.#D=1/0,this.#B=0),Math.max(this.#n,Math.min(this.#t,this.#D-1))}#H(e){return Math.max(this.#n,Math.min(this.#t,e))}#N(){let e=0,t=0,r=0,s=0;for(let l of this.#y)e+=l.bytes,l.durationMs!==void 0&&(t+=l.durationMs,r++,s+=l.durationMs/(l.bytes/(1024*1024)));if(r>0&&t>0)return{throughputBps:e/(t/1e3)*this.#l,latencyMsPerMB:s/r,averageDurationMs:t/r,durationSampleCount:r};if(this.#y.length<2)return{throughputBps:0,latencyMsPerMB:0,averageDurationMs:0,durationSampleCount:0};let i=this.#y[0],a=this.#y[this.#y.length-1].completedAtMs-i.completedAtMs;return{throughputBps:a>0?e/a*1e3:0,latencyMsPerMB:0,averageDurationMs:a>0?a/Math.max(1,this.#y.length-1):0,durationSampleCount:0}}};var z=class{#e;#n;#t;#r;#s;constructor(e){let t=e===0?null:e;this.#e=t,this.#n=t??0,this.#t=Date.now(),this.#r=[],this.#s=null}setLimit(e){let t=e===0?null:e;if(t===null){this.#e=null,this.#n=0,this.#u();let s=this.#r.splice(0);for(let i of s)i.resolve();return}let r=this.#e;this.#e=t,r===null?(this.#n=t,this.#t=Date.now()):(this.#i(),this.#n=Math.min(this.#n,t)),this.#o()}getLimit(){return this.#e}acquire(e){if(this.#e!==null){if(this.#i(),this.#r.length===0&&this.#n>=e){this.#n-=e;return}return this.#a(e)}}#i(){let e=Date.now(),t=(e-this.#t)/1e3;if(t<=0)return;let r=this.#e,s=t*r,i=this.#r.length>0?Math.max(r,this.#r[0].bytes):r;this.#n=Math.min(this.#n+s,i),this.#t=e}#a(e){return new Promise(t=>{this.#r.push({bytes:e,resolve:t}),this.#s===null&&this.#c()})}#c(){if(this.#r.length===0||this.#e===null){this.#s=null;return}let t=this.#r[0].bytes-this.#n,r=t>0?Math.ceil(t/this.#e*1e3):0;if(r<=0){this.#s=null,this.#o();return}this.#s=setTimeout(()=>{this.#s=null,this.#i(),this.#o()},r)}#o(){for(;this.#r.length>0;){if(this.#e===null){let t=this.#r.splice(0);for(let r of t)r.resolve();return}this.#i();let e=this.#r[0];if(this.#n>=e.bytes)this.#n-=e.bytes,this.#r.shift(),e.resolve();else{this.#c();return}}}#u(){this.#s!==null&&(clearTimeout(this.#s),this.#s=null)}};function Mt(n){let e=`[${n}]`;return{info:(...t)=>console.info(e,...t),warn:(...t)=>console.warn(e,...t),error:(...t)=>console.error(e,...t)}}var ot=Mt("transfer");var Ae=class{uploadAssets={};uploadGroups={};#e=new ee;get uploadSpeedState(){return this.#e.serialize()}uploadStats={uploadSpeedMbps:0,timeRemainingSeconds:0,formattedSpeed:"Calculating...",formattedTime:"Calculating..."};dirtyAssetIds=new Set;dirtyGroupIds=new Set;dirtyHistoryGroupIds=new Set;#n(e){e!==0&&this.#e.adjustTotalBytes(-e)}adjustSpeedBaselineForSkippedBytes(e){e!==0&&this.#e.adjustTotalBytes(e)}#t(){Object.values(this.uploadAssets).some(t=>t.status==="queued"||t.status==="in-progress")||this.#e.reset()}#r(e){this.dirtyAssetIds.add(e)}#s(e){this.dirtyGroupIds.add(e)}addUploadAsset({assetId:e,fileReader:t,abortController:r,parentId:s,projectId:i,groupId:o,chunkSize:a,shareContext:l}){this.uploadAssets[e]={assetId:e,totalBytesToUpload:t.size,bytesUploaded:0,status:"queued",fileName:t.name,createdAt:new Date().toISOString(),i:Object.keys(this.uploadAssets).length,parentId:s,projectId:i,groupId:o,retryCount:0,chunkSize:a??0,fileReader:t,abortController:r,shareContext:l},this.#r(e)}updateUploadProgress(e,t){let r=this.uploadAssets[e];if(!r||r.status==="paused"||r.status==="cancelled"||r.status==="success"||r.status==="failed")return;let s=t>0&&r.status==="queued"?"in-progress":r.status,i=Math.min(t,r.totalBytesToUpload);r.bytesUploaded=i,r.status=s,this.#r(e)}markUploadInProgress(e){let t=this.uploadAssets[e];t&&(t.status="in-progress",this.#r(e))}markUploadSuccess(e){let t=this.uploadAssets[e];t&&(t.status="success",t.bytesUploaded=t.totalBytesToUpload,this.#r(e),this.#t(),this.cleanupOnCompletion(e))}markUploadFailed(e,t){let r=this.uploadAssets[e];if(!r)return;let s=r.bytesUploaded;r.status="failed",r.errorMessage=t,r.bytesUploaded=0,this.#r(e),this.#n(s),this.#t(),this.cleanupOnCompletion(e)}removeUploadAsset(e){let r=this.uploadAssets[e]?.bytesUploaded??0;delete this.uploadAssets[e],this.#r(e),this.#n(r),this.#t()}clearAllUploads(){this.uploadAssets={},this.#e.reset()}clearTerminalState(){if(!Object.values(this.uploadAssets).some(t=>t.status==="queued"||t.status==="in-progress"||t.status==="paused")){for(let t of Object.keys(this.uploadAssets))delete this.uploadAssets[t];for(let t of Object.keys(this.uploadGroups))delete this.uploadGroups[t];this.#e.reset()}}resetAssetForRetryQueue(e){let t=this.uploadAssets[e];t&&(t.status="queued",t.bytesUploaded=0,t.errorMessage=void 0,t.retryCount=t.retryCount+1,this.#r(e))}resetAssetForRetrying(e){let t=this.uploadAssets[e];t&&(t.status="queued",t.bytesUploaded=0,t.retryCount=0,this.#r(e))}pauseUpload(e){let t=this.uploadAssets[e];if(!t||t.status!=="queued"&&t.status!=="in-progress")return;let r=0;if(t.chunkedState){let{completedChunkIndices:i,chunkSize:o}=t.chunkedState;for(let a of i){let l=a*o,c=Math.min(l+o,t.totalBytesToUpload);r+=c-l}}let s=t.bytesUploaded-r;t.status="paused",t.bytesUploaded=r,this.#r(e),this.#n(s),this.#t(),t.abortController.abort()}unpauseUpload(e){let t=this.uploadAssets[e];t&&t.status==="paused"&&(t.status="queued",this.#r(e))}pauseUploadGroup(e){let t=this.uploadGroups[e];if(t&&!t.isCreatingFolders){t.isPaused=!0,this.#s(e);for(let r of t.assetIds)this.pauseUpload(r)}}unpauseUploadGroup(e){let t=this.uploadGroups[e];t&&(t.isPaused=!1,this.#s(e))}pauseAllUploads(){for(let e of Object.values(this.uploadGroups))e.isCreatingFolders||this.pauseUploadGroup(e.id)}resumeAllUploads(){for(let e of Object.values(this.uploadGroups))e.isPaused&&this.unpauseUploadGroup(e.id)}markUploadCancelled(e){let t=this.uploadAssets[e];if(!t||t.status==="success"||t.status==="failed"||t.status==="cancelled")return;let r=t.bytesUploaded;t.status="cancelled",this.#r(e),this.#n(r),this.#t(),this.cleanupOnCompletion(e)}setChunkedState(e,t){let r=this.uploadAssets[e];r&&(r.chunkedState=t,this.#r(e))}addCompletedChunkIndex(e,t){let r=this.uploadAssets[e];!r||!r.chunkedState||(r.chunkedState={...r.chunkedState,completedChunkIndices:[...r.chunkedState.completedChunkIndices,t]},this.#r(e))}clearChunkedState(e){let t=this.uploadAssets[e];t&&(t.chunkedState=void 0,this.#r(e))}hasGroupsCreatingFolders(){return Object.values(this.uploadGroups).some(e=>e.isCreatingFolders===!0)}areAllUploadsPaused(){return st(this.uploadAssets)}hasPausedUploads(){return it(this.uploadAssets)}getUploadAsset(e){return this.uploadAssets[e]}getSerializableAsset(e){let t=this.uploadAssets[e];if(t)return this.#c(t)}getUploadSummary(){return Z(this.#u())}getAllUploadAssetsSortedByRecent(){return Object.values(this.uploadAssets).map(e=>this.#c(e)).sort((e,t)=>t.i-e.i)}getGroupAssets(e){let t=this.uploadGroups[e];return!t||!t.assetIds?[]:t.assetIds.map(r=>this.uploadAssets[r]).filter(Boolean).map(r=>this.#c(r))}getGroupAssetsInternal(e){let t=this.uploadGroups[e];return!t||!t.assetIds?[]:t.assetIds.map(r=>this.uploadAssets[r]).filter(Boolean)}addUploadGroup(e){let t=crypto.randomUUID();return this.uploadGroups[t]={...e,id:t,fileReaders:new Map},this.#s(t),t}updateUploadGroup(e,t){let r=this.uploadGroups[e];r&&(Object.assign(r,t),this.#s(e))}addAssetToGroup(e,t){let r=this.uploadGroups[e];r&&(r.assetIds.push(t),this.#s(e))}finalizeEmptyGroup({groupId:e,status:t,errorMessage:r}){let s=this.uploadGroups[e];s&&(s.assetIds.length>0||s.finalizedStatus||(s.finalizedStatus=t,s.errorMessage=r,s.isCreatingFolders=!1,s.completedAt=new Date().toISOString(),this.#s(e),this.dirtyHistoryGroupIds.add(e)))}removeUploadGroup(e){let t=this.uploadGroups[e];if(t)for(let r of t.assetIds)delete this.uploadAssets[r],this.#r(r);delete this.uploadGroups[e],this.#s(e)}getUploadGroup(e){let t=this.uploadGroups[e];if(t)return this.#o(t)}getAllUploadGroups(){return Object.values(this.uploadGroups).map(e=>this.#o(e)).sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}getUploadGroupProgress(e){let t=this.uploadGroups[e];if(!t)return null;let r=this.getGroupAssets(e);return rt(this.#o(t),r)}getUploadGroupStatus(e){let t=this.uploadGroups[e];if(!t)return null;let r=this.getGroupAssets(e);return be(this.#o(t),r)}getAssetsByParentId(e){return Object.values(this.uploadAssets).filter(t=>t.parentId===e).map(t=>this.#c(t))}getActiveUploadGroups(){return Object.values(this.uploadGroups).filter(e=>{let t=this.getUploadGroupStatus(e.id);return t&&["queued","creating-folders","in-progress"].includes(t)}).map(e=>this.#o(e))}cleanupOnCompletion(e){let t=this.uploadAssets[e];if(!t)return;let r=t.groupId;if(r){let i=this.uploadGroups[r];if(i){let o=this.getGroupAssets(r),a=this.#o(i);this.dirtyHistoryGroupIds.add(r),!o.some(c=>c.status==="queued"||c.status==="in-progress")&&!i.completedAt&&(i.completedAt=new Date().toISOString(),this.#s(r))}}let s=this.getUploadSummary();if(s.cancelledAssetCount+s.failedAssetCount+s.successAssetCount===s.totalAssetCount)for(let i of Object.keys(this.uploadAssets)){let o=this.uploadAssets[i];o&&(o.bytesUploaded=0,this.#r(i))}}updateUploadStats(){let e=this.getUploadSummary(),t=e.queuedAssetCount>0||e.inProgressAssetCount>0;t&&this.#e.sample(e.totalBytesUploaded);let r=this.#e.isWarmedUp?this.#e.speedMbps:0,s=t&&this.#e.isWarmedUp?this.#e.etaSeconds(e.totalBytesToUpload-e.totalBytesUploaded):0;this.uploadStats={uploadSpeedMbps:r,timeRemainingSeconds:s,formattedSpeed:this.#i(r),formattedTime:this.#a(s)}}#i(e){return!Number.isFinite(e)||e<=0?"Calculating...":e<1?`${(e*1e3).toFixed(0)} Kbps`:`${e.toFixed(1)} Mbps`}#a(e){if(!Number.isFinite(e)||e<=0)return"Calculating...";let t=Math.floor(e/3600),r=Math.floor(e%3600/60),s=Math.floor(e%60);return t>0?`${t}h ${r}m left`:r>0?`${r}m ${s}s left`:`${s}s left`}buildHistoryItem(e){let t=this.uploadGroups[e];if(!t)return null;let r=this.getGroupAssets(e),s=this.#o(t);return{groupId:t.id,name:t.name,type:t.type,fileCount:t.fileCount,folderCount:t.folderCount,topLevelFileCount:t.topLevelFileCount,topLevelFolderCount:t.topLevelFolderCount,status:et(s,r),createdAt:t.createdAt,completedAt:t.completedAt,rootDirectoryId:t.rootDirectoryId,projectId:t.projectId,errorMessage:t.errorMessage,conflictResolution:t.conflictResolution}}#c({fileReader:e,abortController:t,shareContext:r,...s}){return s}#o({fileReaders:e,...t}){return t}#u(){let e={};for(let[t,r]of Object.entries(this.uploadAssets))e[t]=this.#c(r);return e}#p(){let e={};for(let[t,r]of Object.entries(this.uploadGroups))e[t]=this.#o(r);return e}getSerializableSnapshot(){return{uploadAssets:this.#u(),uploadGroups:this.#p(),uploadStats:{...this.uploadStats},uploadSpeedState:this.uploadSpeedState}}getDirtyDelta(){let e={};for(let r of this.dirtyAssetIds){let s=this.uploadAssets[r];s&&(e[r]=this.#c(s))}let t={};for(let r of this.dirtyGroupIds){let s=this.uploadGroups[r];s&&(t[r]=this.#o(s))}return{assets:e,groups:t}}clearDirtyFlags(){this.dirtyAssetIds.clear(),this.dirtyGroupIds.clear(),this.dirtyHistoryGroupIds.clear()}};function Wn(n,e){let t=new Date(n).getTime(),r=Date.now();return t-r<=e}var Fe=class{#e;#n=new Map;#t=new Map;constructor(e){this.#e=e}seedToken(e,t,r){this.#n.set(e,{token:t,expiresAt:r})}async getToken(e,t){let r=this.#n.get(e);if(r&&!Wn(r.expiresAt,3e5))return r.token;let s=this.#t.get(e);if(s)return s;let i=t?D(t):void 0,o=this.#e.post(`/assets/${e}/token`,{},i).then(a=>{if(!a.token)throw new Error("Token refresh failed: no token in response");return this.#n.set(e,{token:a.token,expiresAt:a.token_expires_at}),this.#t.delete(e),a.token}).catch(a=>{throw this.#t.delete(e),a});return this.#t.set(e,o),o}clearCache(e){e?this.#n.delete(e):this.#n.clear()}};var we=class{#e=[];registerAsset(e){this.#e.push({assetId:e.assetId,totalChunks:e.totalChunks,nextChunkToClaim:0,completedChunkIndices:new Set(e.completedChunkIndices),isPaused:!1})}claimNextChunk(){for(let e of this.#e)if(!e.isPaused)for(;e.nextChunkToClaim<e.totalChunks;){let t=e.nextChunkToClaim;if(e.nextChunkToClaim++,!e.completedChunkIndices.has(t))return{assetId:e.assetId,chunkIndex:t}}return null}markChunkCompleted(e,t){let r=this.#n(e);return r?(r.completedChunkIndices.add(t),r.completedChunkIndices.size>=r.totalChunks):!1}pauseAsset(e){let t=this.#n(e);t&&(t.isPaused=!0)}unpauseAsset(e){let t=this.#n(e);t&&(t.isPaused=!1,this.#t(t))}removeAsset(e){this.#e=this.#e.filter(t=>t.assetId!==e)}hasAsset(e){return this.#e.some(t=>t.assetId===e)}isAssetComplete(e){let t=this.#n(e);return t?t.completedChunkIndices.size>=t.totalChunks:!1}clear(){this.#e=[]}#n(e){return this.#e.find(t=>t.assetId===e)}#t(e){for(let t=0;t<e.totalChunks;t++)if(!e.completedChunkIndices.has(t)){e.nextChunkToClaim=t;return}e.nextChunkToClaim=e.totalChunks}};var qn=/[/\\:*?"<>|\x00-\x1F]/g,Kn=["CON","PRN","AUX","NUL","COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","LPT1","LPT2","LPT3","LPT4","LPT5","LPT6","LPT7","LPT8","LPT9"];function $(n){let e=n.replace(qn,"_");e=e.replace(/[. ]+$/,""),(!e||e==="."||e==="..")&&(e="unnamed");let t=e.includes(".")?e.substring(0,e.lastIndexOf(".")):e;Kn.includes(t.toUpperCase())&&(e=`_${e}`);let r=new TextEncoder;if(r.encode(e).length>255){let s=e.lastIndexOf("."),i=s>0?e.substring(s):"",o=s>0?e.substring(0,s):e,l=255-r.encode(i).length;for(;r.encode(o).length>l&&o.length>0;)o=o.slice(0,-1);e=o+i}return e}var L=class extends Error{constructor(){super("Upload cancelled"),this.name="CancelledError"}};function _(n){return n instanceof L||n instanceof Error&&n.name==="CancelledError"||n instanceof Error&&n.name==="CanceledError"||n instanceof Error&&n.name==="AbortError"}function er(n){return _(n)||n instanceof Error&&n.name==="NoAuthError"}function tr(n){return new Promise(e=>setTimeout(e,n))}function nr(n){return n instanceof Blob?n.size:n.byteLength}var ne=class{#e;#n;#t;#r;#s;#i;#a;#c;#o;#u;#p;#l;#U;#y=null;#F=0;#k=!1;#C=[];#b=new Set;#R=!1;#P=!1;#T=!1;#m=[];#A=!1;#I=!1;#d=new we;#v=0;#f=new Map;#w=new Map;#D=[];#B=!1;#L=null;#O;#_="keep_both";#x=new Map;#M=null;#h=!1;#g=null;#E=!1;constructor(e){this.#e=e.httpClient,this.#n=new Fe(e.httpClient),this.#t=new Ae,this.#r=e.historyStore??null,this.#s=e.settingsStore??null,this.#i=e.analytics??null,this.#a=e.logger??ot,this.#c=e.onChange??null,this.#o=e.onClear??null,this.#u=e.onSummary??null,this.#p=e.onConcurrencyAdjusted??null,this.#U=e.deltaIntervalMs??333;let t=e.maxConcurrency??4;if(e.adaptiveConcurrency!==!1){let r=e.adaptiveConcurrencyConfig;this.#g=new te({initialConcurrency:r?.initialConcurrency??Math.min(4,t),minConcurrency:r?.minConcurrency??1,maxConcurrency:r?.maxConcurrency??t,errorThreshold:r?.errorThreshold,cooldownSeconds:r?.cooldownSeconds??10,plateauThreshold:r?.plateauThreshold,onChange:s=>{let i=this.#l;if(this.setMaxConcurrency(s),i===s)return;let o=this.#E?"reset":s>i?"probe_increase":"error_decrease",a=Math.round(this.#g.speedBps*8/1e6*100)/100,l=Math.round(this.#g.latencyMsPerMB*100)/100;this.#a.info(`Adaptive concurrency: ${i} \u2192 ${s} (${o}), measuredAt=${i}, speed=${a}Mbps, latency=${l}ms/MB`),this.#p?.({previousConcurrency:i,newConcurrency:s,reason:o,speedMbps:a,latencyMsPerMB:l})},now:r?.now}),this.#l=this.#g.concurrency}else this.#l=t;this.#r&&(this.#C=this.#r.load()),this.#s&&(this.#L=this.#s.getBandwidthLimitBps(),this.#_=this.#s.getConflictResolution()),this.#O=new z(this.#L),(this.#c||this.#u)&&(this.#y=setInterval(()=>{this.#ce()},this.#U)),this.#i&&(this.#M=setInterval(()=>{this.#de()},6e4))}startUpload(e){let t=e.assetId||crypto.randomUUID(),r=!!e.assetId,s;if(r){let o=this.#t.getUploadAsset(t);if(!o)throw new Error(`Cannot retry: asset ${t} not found`);s=o.chunkSize}else{if(e.chunkSize===void 0||e.chunkSize===null)throw new Error("chunkSize is required for new uploads");s=e.chunkSize}let i=new AbortController;if(r){if(this.#t.getUploadAsset(t).status==="cancelled")return t;e.resetRetryCount&&this.#t.resetAssetForRetrying(t);let a=this.#t.getUploadAsset(t);a.abortController=i,a.fileReader=e.fileReader,e.shareContext&&(a.shareContext=e.shareContext)}else this.#t.addUploadAsset({assetId:t,fileReader:e.fileReader,abortController:i,parentId:e.directoryId,projectId:e.projectId,groupId:e.groupId,chunkSize:s,shareContext:e.shareContext});return this.#m.push(t),this.#G(),this.#S(),t}startGroupUpload(e){this.#t.clearTerminalState();let t=this.#t.addUploadGroup({type:e.type,name:e.name,assetIds:[],fileCount:e.fileCount,folderCount:e.folderCount,topLevelFileCount:e.topLevelFileCount,topLevelFolderCount:e.topLevelFolderCount,isCreatingFolders:!1,isPaused:!1,createdAt:new Date().toISOString(),rootDirectoryId:e.rootDirectoryId,projectId:e.projectId,retryCount:0,conflictResolution:e.conflictResolutionOverride??this.#_});return this.#x.set(t,Date.now()),this.#i?.("upload:started",{file_count:e.fileCount,total_bytes:e.totalBytes??0,has_folders:e.folderCount>0,project_id:e.projectId}),this.#t.dirtyHistoryGroupIds.add(t),this.#$(),this.#S(),t}pauseUpload(e){let t=this.#t.getUploadAsset(e);this.#t.pauseUpload(e),this.#m=this.#m.filter(r=>r!==e),this.#d.pauseAsset(e),!this.#h&&t&&this.#i&&this.#i("upload:file_paused",{file_name:t.fileName,file_size:t.totalBytesToUpload,bytes_uploaded:t.bytesUploaded,project_id:t.projectId??""}),this.#S()}unpauseUpload(e){this.#t.unpauseUpload(e),this.#S()}cancelUpload(e){let t=this.#t.getUploadAsset(e);if(!t||t.status==="success"||t.status==="failed"||t.status==="cancelled")return;let r=t.fileName,s=t.totalBytesToUpload,i=t.bytesUploaded,o=t.projectId,a=t.chunkedState?.assetId;(t.status==="queued"||t.status==="in-progress")&&t.abortController.abort(),this.#m=this.#m.filter(l=>l!==e),this.#d.removeAsset(e),this.#f.delete(e),this.#w.delete(e),this.#t.markUploadCancelled(e),this.#t.clearChunkedState(e),t.fileReader.close?.(),!this.#h&&this.#i&&this.#i("upload:file_cancelled",{file_name:r,file_size:s,bytes_uploaded:i,project_id:o??""}),this.#S(),this.#N(),this.#G(),this.#Q(),a&&(this.#D.push(a),this.#X())}cancelAllUploads(){let e=this.#J();this.#h=!0;try{let r=Object.values(this.#t.uploadAssets).filter(s=>s.status==="queued"||s.status==="in-progress"||s.status==="paused");for(let s of r)this.cancelUpload(s.assetId)}finally{this.#h=!1}this.#i?.("upload:all_cancelled",e)}retryUpload(e){let t=this.#t.getUploadAsset(e);t&&t.status==="failed"&&this.startUpload({fileReader:t.fileReader,directoryId:t.parentId??"",projectId:t.projectId,groupId:t.groupId,assetId:e,resumeChunked:t.chunkedState,resetRetryCount:!0,shareContext:t.shareContext})}resumeUpload(e){let t=this.#t.getUploadAsset(e);if(!t||t.status!=="paused")return;!this.#h&&this.#i&&this.#i("upload:file_resumed",{file_name:t.fileName,file_size:t.totalBytesToUpload,bytes_uploaded:t.bytesUploaded,project_id:t.projectId??""});let r=new AbortController;t.abortController=r,this.#t.unpauseUpload(e),this.#d.hasAsset(e)?(this.#d.unpauseAsset(e),this.#S(),this.#d.isAssetComplete(e)?this.#Y(e).catch(s=>{this.#z(e,s)}):this.#N()):this.startUpload({fileReader:t.fileReader,directoryId:t.parentId??"",projectId:t.projectId,groupId:t.groupId,assetId:e,resumeChunked:t.chunkedState,shareContext:t.shareContext})}pauseUploadGroup(e){let t=this.#t.uploadGroups[e];if(!t)return;let r=this.#h;this.#h=!0,this.#t.pauseUploadGroup(e);for(let s of t.assetIds)this.#m=this.#m.filter(i=>i!==s),this.#d.pauseAsset(s);this.#h=r,this.#h||this.#te(e,t,"upload:group_paused"),this.#S()}unpauseUploadGroup(e){this.#t.unpauseUploadGroup(e),this.#S()}cancelUploadGroup(e){let t=this.#t.uploadGroups[e];if(!t)return;let{totalBytes:r,bytesUploaded:s,filesRemaining:i}=this.#ee(t),o=this.#h;this.#h=!0;for(let a of t.assetIds)this.cancelUpload(a);t.assetIds.length===0&&(this.#t.finalizeEmptyGroup({groupId:e,status:"cancelled"}),this.#$(),this.#S()),this.#h=o,this.#h||this.#i?.("upload:group_cancelled",{file_count:t.assetIds.length,files_remaining:i,total_bytes:r,bytes_uploaded:s,project_id:t.projectId}),this.#x.delete(e)}resumeUploadGroup(e){let t=this.#t.uploadGroups[e];if(!t)return;this.#h||this.#te(e,t,"upload:group_resumed");let r=this.#h;this.#h=!0,this.#t.unpauseUploadGroup(e);for(let s of t.assetIds){let i=this.#t.getUploadAsset(s);i&&i.status==="paused"&&this.resumeUpload(s)}this.#h=r}retryUploadGroup(e){let t=this.#t.uploadGroups[e];if(t)for(let r of t.assetIds){let s=this.#t.getUploadAsset(r);s&&s.status==="failed"&&this.retryUpload(r)}}setGroupCreatingFolders(e,t){this.#t.updateUploadGroup(e,{isCreatingFolders:t}),this.#S()}markEmptyGroupFailed(e,t){let r=this.#t.uploadGroups[e];r&&(r.assetIds.length>0||r.finalizedStatus||(this.#a.error("Empty group upload failed",{groupId:e,groupName:r.name,errorMessage:t}),this.#t.finalizeEmptyGroup({groupId:e,status:"all-failed",errorMessage:t}),this.#$(),this.#x.delete(e),this.#S()))}markEmptyGroupCompleted(e){this.#t.finalizeEmptyGroup({groupId:e,status:"success"}),this.#$(),this.#x.delete(e),this.#S()}addAssetToGroup(e,t){this.#t.addAssetToGroup(e,t)}pauseAllUploads(){let e=this.#J();this.#h=!0;try{for(let t of Object.values(this.#t.uploadAssets))t.groupId||this.pauseUpload(t.assetId);for(let t of Object.values(this.#t.uploadGroups))t.isCreatingFolders||this.pauseUploadGroup(t.id)}finally{this.#h=!1}this.#i?.("upload:all_paused",e),this.#S()}resumeAllUploads(){let e=this.#J();this.#h=!0;try{for(let t of Object.values(this.#t.uploadAssets))!t.groupId&&t.status==="paused"&&this.resumeUpload(t.assetId);for(let t of Object.values(this.#t.uploadGroups))t.isPaused&&this.resumeUploadGroup(t.id)}finally{this.#h=!1}this.#i?.("upload:all_resumed",e),this.#S()}clearAllUploads(){this.#m=[],this.#d.clear(),this.#f.clear(),this.#w.clear(),this.#t.clearAllUploads(),this.#t.uploadGroups={},this.#g&&(this.#E=!0,this.#g.reset(),this.#E=!1),this.#o?.({all:!0}),this.#u?.(this.#j())}clearHistory(){this.#C=[],this.#r?.clear(),this.#R=!0,this.#b.clear(),this.#T=!0,this.#S()}removeHistoryItem(e){this.#C=this.#C.filter(t=>t.groupId!==e),this.#r?.remove(e),this.#b.add(e),this.#T=!0,this.#S()}removeGroup(e){this.#t.removeUploadGroup(e),this.#C=this.#C.filter(t=>t.groupId!==e),this.#r?.remove(e),this.#b.add(e),this.#T=!0,this.#o?.({groupId:e}),this.#u?.(this.#j()),this.#S()}getHttpClient(){return this.#e}setBandwidthLimit(e){let t=e!==this.#L;this.#L=e,this.#O.setLimit(e),this.#s?.setBandwidthLimitBps(e),t&&this.#g&&(this.#E=!0,this.#g.reset(),this.#E=!1),this.#T=!0,this.#S()}getBandwidthLimit(){return this.#L}setConflictResolution(e){this.#_=e,this.#s?.setConflictResolution(e),this.#T=!0,this.#S()}getConflictResolution(){return this.#_}getGroupConflictResolution(e){return this.#t.getUploadGroup(e)?.conflictResolution??this.#_}setMaxConcurrency(e){this.#l=e,this.#N()}getSnapshot(){return this.#t.updateUploadStats(),{...this.#t.getSerializableSnapshot(),uploadHistory:[...this.#C??[]],uploadSummary:this.#j(),bandwidthLimitBps:this.#L,conflictResolution:this.#_}}getUploadAsset(e){return this.#t.getSerializableAsset(e)}getUploadSummary(){return this.#j()}getGroupAssets(e){return this.#t.getGroupAssets(e)}getUploadGroupStatus(e){return this.#t.getUploadGroupStatus(e)}getUploadGroupProgress(e){return this.#t.getUploadGroupProgress(e)}hasGroupsCreatingFolders(){return this.#t.hasGroupsCreatingFolders()}areAllUploadsPaused(){return this.#t.areAllUploadsPaused()}hasPausedUploads(){return this.#t.hasPausedUploads()}hasActiveUploads(){return nt(this.#t.getSerializableSnapshot().uploadAssets)}getServerAssetIdsToCancel(){return tt(this.#t.getSerializableSnapshot().uploadAssets)}async cancelActiveServerUploads(){let e=this.getServerAssetIdsToCancel();if(e.length!==0)try{await this.#e.post("/assets/cancel-uploads",{asset_ids:e})}catch{await this.#e.post("/assets/cancel-uploads",{asset_ids:e})}}destroy(){this.#P=!0,this.#y&&(clearInterval(this.#y),this.#y=null),this.#M&&(clearInterval(this.#M),this.#M=null),this.#m=[],this.#d.clear();for(let e of Object.values(this.#t.uploadAssets))e.abortController.abort(),e.fileReader.close?.()}#G(){this.#I||(this.#I=!0,queueMicrotask(()=>{this.#I=!1,this.#W().catch(e=>{this.#a.error("Initiation pipeline error",{queueLength:this.#m.length},e)})}))}async#W(){if(!this.#A){this.#A=!0;try{await this.#q()}finally{this.#A=!1}}}async#q(){for(;this.#m.length>0&&!(this.#f.size>5);){let e=Math.min(this.#m.length,20-this.#f.size);if(e<=0)break;let t=[],r=[];for(let s=0;s<e&&this.#m.length>0;s++){let i=this.#m[0],o=this.#t.getUploadAsset(i);if(!o||o.status==="cancelled"){this.#m.shift(),s--;continue}if(this.#m.shift(),r.push(i),o.chunkedState)try{this.#V(i,o),this.#N()}catch(a){_(a)||this.#z(i,a)}else t.push(i)}if(t.length>0){let s=new Map;for(let i of t){let a=this.#t.getUploadAsset(i)?.shareContext?.shareId??"",l=s.get(a);l||(l=[],s.set(a,l)),l.push(i)}for(let i of s.values())try{await this.#H(i)}catch(o){for(let a of i)this.#z(a,o instanceof Error?o:new Error(String(o)))}this.#N()}}}#V(e,t){let r=t.chunkedState,s={serverAssetId:r.assetId,chunkIds:r.chunkIds,chunkSize:r.chunkSize,totalChunks:r.totalChunks,sizeBytes:r.sizeBytes},i=r.completedChunkIndices;this.#f.set(e,s);let o=new Array(s.totalChunks).fill(0);if(i.length>0){for(let l of i){let c=l*s.chunkSize,u=Math.min(c+s.chunkSize,t.totalBytesToUpload);o[l]=u-c}let a=o.reduce((l,c)=>l+c,0);this.#t.updateUploadProgress(e,a)}if(this.#w.set(e,o),s.totalChunks===0||i.length>=s.totalChunks){this.#Y(e).catch(a=>{this.#z(e,a)});return}this.#d.registerAsset({assetId:e,totalChunks:s.totalChunks,completedChunkIndices:i})}async#H(e){let t=[],r=[];for(let a of e){let l=this.#t.getUploadAsset(a);if(!l||l.status==="cancelled")continue;let c=$(l.fileName),u=l.groupId?this.#t.getUploadGroup(l.groupId)?.conflictResolution??this.#_:this.#_,d=(()=>{switch(u){case"keep_both":return{auto_rename:"parenthesized"};case"replace":return{conflict_resolution:"replace"};case"skip":return{conflict_resolution:"skip"}}})();t.push({directory_id:l.parentId,id:a,name:c,size_bytes:l.totalBytesToUpload,...d}),r.push(a)}if(t.length===0)return;let s=this.#t.getUploadAsset(r[0]),i=s?.shareContext?D(s.shareContext):void 0,o=await this.#e.post("/assets/chunked/initiate",t,i);for(let a=0;a<r.length;a++){let l=r[a],c=o[a];if(!c||c.error){this.#z(l,new Error(c?.error??"Unknown batch initiation error"));continue}if(c.skipped){let S=this.#t.getUploadAsset(l);S&&(this.#t.adjustSpeedBaselineForSkippedBytes(S.totalBytesToUpload),this.#t.markUploadSuccess(l),this.#t.dirtyHistoryGroupIds.add(S.groupId??""),this.#$(),S.fileReader.close?.());continue}let u=c.result,d=this.#t.getUploadAsset(l);if(!d||d.status==="cancelled"||d.status==="paused"){(!d||d.status==="cancelled")&&(this.#D.push(u.asset_id),this.#X());continue}let m=Math.ceil(d.totalBytesToUpload/u.chunk_size),g=Array.from({length:m},()=>crypto.randomUUID());this.#n.seedToken(u.asset_id,u.token,u.token_expires_at);let p={serverAssetId:u.asset_id,chunkIds:g,chunkSize:u.chunk_size,totalChunks:m,sizeBytes:d.totalBytesToUpload};this.#t.setChunkedState(l,{assetId:p.serverAssetId,chunkIds:p.chunkIds,completedChunkIndices:[],chunkSize:p.chunkSize,totalChunks:p.totalChunks,sizeBytes:p.sizeBytes}),this.#f.set(l,p);let A=new Array(p.totalChunks).fill(0);if(this.#w.set(l,A),p.totalChunks===0){this.#Y(l).catch(S=>{this.#z(l,S)});continue}this.#d.registerAsset({assetId:l,totalChunks:p.totalChunks,completedChunkIndices:[]})}}#N(){if(!this.#P)for(;this.#v<this.#l;){let e=this.#d.claimNextChunk();if(!e)break;this.#v++;let{assetId:t,chunkIndex:r}=e,s=this.#g?.generation;this.#re(t,r,s).then(i=>{this.#v--,this.#ie(t,r,i),this.#N()}).catch(i=>{if(this.#v--,_(i)){this.#N();return}this.#oe(t,r,i),this.#N()})}}async#re(e,t,r){let s;for(let i=0;i<3;i++)try{let o=this.#w.get(e);return o&&(o[t]=0,this.#K(e)),await this.#se(e,t,r)}catch(o){if(_(o))throw o;if(s=o instanceof Error?o:new Error(String(o)),this.#g?.recordError(),this.#ae(e,t,s,i),i===2)throw s;let a=this.#w.get(e);a&&(a[t]=0,this.#K(e));let l=1e3*Math.pow(2,i);await tr(l)}throw s||new Error("Unknown error during chunk upload")}async#se(e,t,r){let s=this.#t.getUploadAsset(e);if(!s)throw new L;if(s.abortController.signal.aborted)throw new L;let i=this.#f.get(e);if(!i)throw new Error(`No chunk metadata for asset ${e}`);let o=t*i.chunkSize,a=Math.min(o+i.chunkSize,s.totalBytesToUpload),l=await s.fileReader.readChunk(o,a),c=nr(l);if(s.abortController.signal.aborted)throw new L;let u=i.chunkIds[t],d=await this.#n.getToken(i.serverAssetId,s.shareContext),m=`/uploads/chunks/${u}`,g=Date.now(),p=await this.#e.putWithToken(m,l,d,{signal:s.abortController.signal,onProgress:T=>{let E=this.#w.get(e);E&&(E[t]=T,this.#K(e))},contentType:"application/octet-stream",limiter:this.#O}),A=Date.now(),S=p.uploadCompletedAtMs??A,y=S-g;if(!p.status||p.status<200||p.status>=300)throw this.#a.error("Chunk upload returned unexpected status",{chunkIndex:t,chunkId:u,assetId:e,serverAssetId:i.serverAssetId,chunkSizeBytes:c,durationMs:y,httpStatus:p.status,statusText:p.statusText,responseBody:p.data,responseHeaders:p.headers}),new Error(`Chunk ${t} upload failed: unexpected status ${p.status}`);let Se=this.#w.get(e);return Se&&(Se[t]=c,this.#K(e)),{durationMs:y,startedAtMs:g,completedAtMs:S,adaptiveGeneration:r}}#K(e){let t=this.#w.get(e);if(!t)return;let r=t.reduce((s,i)=>s+i,0);this.#t.updateUploadProgress(e,r)}#ie(e,t,r){if(this.#g){let i=this.#f.get(e);if(i){let o=t*i.chunkSize,l=Math.min(o+i.chunkSize,i.sizeBytes)-o;this.#g.recordSuccess(l,r.durationMs,{generation:r.adaptiveGeneration,startedAtMs:r.startedAtMs,completedAtMs:r.completedAtMs})}}this.#t.addCompletedChunkIndex(e,t),this.#d.markChunkCompleted(e,t)&&this.#Y(e).catch(i=>{this.#z(e,i)})}#oe(e,t,r){this.#z(e,r)}#ae(e,t,r,s){if(!this.#i)return;let i=this.#t.getUploadAsset(e);if(!i)return;let o=this.#f.get(e);if(!o)return;let a=t*o.chunkSize,c=Math.min(a+o.chunkSize,o.sizeBytes)-a,u=r,d=typeof u.code=="string"?u.code:null,m=u.response?.status,g=typeof m=="number"?m:null,p=r.cause?r.cause instanceof Error?r.cause.message:String(r.cause):null;this.#i("upload:chunk_error",{file_name:i.fileName,file_size:i.totalBytesToUpload,chunk_index:t,chunk_size:c,chunks_total:o.totalChunks,attempt:s+1,max_attempts:3,is_final_attempt:s===2,error_type:r.name,error_message:r.message,error_code:d,http_status:g,error_stack:r.stack??null,error_cause:p,project_id:i.projectId??""})}#le(e,t,r,s){if(!this.#i||_(t))return;let i=t instanceof Error?t.message:"Unknown error",o=t,a=t instanceof Error&&t.cause?t.cause instanceof Error?t.cause.message:String(t.cause):null,l=typeof o.code=="string"?o.code:null,c=o.response?.status,u=typeof c=="number"?c:null,d=this.#f.get(e.assetId);this.#i("upload:file_error",{file_name:e.fileName,file_size:e.totalBytesToUpload,bytes_uploaded:e.bytesUploaded,chunks_completed:e.chunkedState?.completedChunkIndices.length??0,chunks_total:d?.totalChunks??0,attempt:r+1,max_attempts:4,is_final_attempt:s,error_type:t instanceof Error?t.name:"Unknown",error_message:i,error_code:l,http_status:u,error_stack:t instanceof Error?t.stack??null:null,error_cause:a,project_id:e.projectId??""})}async#Y(e){let t=this.#t.getUploadAsset(e);if(!t)return;let r=this.#f.get(e);if(!r)return;if(t.abortController.signal.aborted)throw new L;let s=crypto.randomUUID(),i=JSON.stringify(r.chunkIds),o=new TextEncoder().encode(i),a=await this.#n.getToken(r.serverAssetId,t.shareContext),l=`/uploads/manifests/${s}`;try{await this.#e.putWithToken(l,o,a,{signal:t.abortController.signal,contentType:"application/json"})}catch(c){throw _(c)||this.#a.error("Manifest upload failed",{assetId:e,serverAssetId:r.serverAssetId,manifestId:s},c),c}if(t.abortController.signal.aborted)throw new L;try{let c=t.shareContext?D(t.shareContext):void 0;await this.#e.post(`/assets/${r.serverAssetId}/revisions/commit`,{manifest_id:s,size_bytes:r.sizeBytes,is_initial_upload:!0,client_performed_at:new Date().toISOString()},c)}catch(c){throw this.#a.error("Commit revision failed",{assetId:e,serverAssetId:r.serverAssetId,manifestId:s,sizeBytes:r.sizeBytes},c),c}this.#t.markUploadSuccess(e),this.#t.clearChunkedState(e),this.#$(),this.#S(),this.#f.delete(e),this.#w.delete(e),this.#d.removeAsset(e),await t.fileReader.close?.(),this.#ne(e),this.#G(),this.#Q()}#z(e,t){let r=this.#t.getUploadAsset(e);if(!r||_(t)||r.status==="paused"||r.status==="cancelled")return;let s=r.retryCount,i=s>=3||er(t);if(this.#le(r,t,s,i),i){let o=t instanceof Error?t.message:"Unknown error";this.#a.error("Asset upload permanently failed",{assetId:e,fileName:r.fileName,totalRetries:s,bytesUploaded:r.bytesUploaded,totalBytes:r.totalBytesToUpload,chunksCompleted:r.chunkedState?.completedChunkIndices.length??0},t),r.abortController.abort(),this.#t.markUploadFailed(e,o),this.#d.removeAsset(e),this.#f.delete(e),this.#w.delete(e),this.#$(),this.#S(),this.#ne(e),this.#G(),this.#Q()}else{this.#a.warn("Asset upload failed, scheduling retry",{assetId:e,fileName:r.fileName,retryAttempt:s+1,maxRetries:3},t);let o=r.chunkedState;r.abortController.abort(),this.#d.removeAsset(e),this.#f.delete(e),this.#w.delete(e),this.#t.resetAssetForRetryQueue(e),this.#S(),this.#G();let a=2e3*Math.pow(2,s);setTimeout(()=>{if(this.#P)return;let l=this.#t.getUploadAsset(e);!l||l.status!=="queued"||this.startUpload({fileReader:l.fileReader,directoryId:l.parentId??"",projectId:l.projectId,groupId:l.groupId,assetId:e,resumeChunked:o,shareContext:l.shareContext})},a)}}#Q(){this.#g&&(this.hasActiveUploads()||(this.#E=!0,this.#g.reset(),this.#E=!1))}#X(){this.#B||(this.#B=!0,queueMicrotask(()=>{this.#B=!1;let e=this.#D.splice(0);e.length!==0&&this.#e.post("/assets/cancel-uploads",{asset_ids:e}).catch(t=>{this.#a.error("Failed to batch abort uploads",{assetIds:e},t)})}))}#j(){return Z(this.#t.getSerializableSnapshot().uploadAssets)}#S(){this.#k||(this.#k=!0,queueMicrotask(()=>{this.#k=!1,this.#ue()}))}#ce(){this.#Z(!0)}#ue(){this.#Z(!1)}#Z(e){if(this.#P||!this.#c&&!this.#u)return;e?this.#t.updateUploadStats():(this.#F++,this.#F%3===0&&this.#t.updateUploadStats());let t=this.#t.getDirtyDelta();if(!this.#T&&Object.keys(t.assets).length===0&&Object.keys(t.groups).length===0&&this.#t.dirtyHistoryGroupIds.size===0)return;this.#T=!1,this.#t.dirtyHistoryGroupIds.size>0&&this.#$();let s=this.#t.dirtyHistoryGroupIds.size>0?this.#pe():void 0,i=this.#R?!0:void 0,o=this.#b.size>0?[...this.#b]:void 0;this.#R=!1,this.#b.clear();let a=this.#j(),l={assets:t.assets,groups:t.groups,uploadStats:{...this.#t.uploadStats},uploadSpeedState:this.#t.uploadSpeedState,historyItems:s,removedHistoryGroupIds:o,historyCleared:i,uploadSummary:a,bandwidthLimitBps:this.#L,conflictResolution:this.#_};this.#t.clearDirtyFlags(),this.#c?.(l),this.#u?.(a)}#ee(e){let t=0,r=0,s=0;for(let i of e.assetIds){let o=this.#t.getUploadAsset(i);o&&(t+=o.totalBytesToUpload,r+=o.bytesUploaded,o.status!=="success"&&o.status!=="failed"&&o.status!=="cancelled"&&s++)}return{totalBytes:t,bytesUploaded:r,filesRemaining:s}}#J(){let e=0,t=0,r=0,s=0;for(let i of Object.values(this.#t.uploadGroups)){e++;for(let o of i.assetIds){let a=this.#t.getUploadAsset(o);a&&(a.status==="success"||a.status==="failed"||a.status==="cancelled"||(t++,r+=a.totalBytesToUpload,s+=a.bytesUploaded))}}return{group_count:e,file_count:t,total_bytes:r,bytes_uploaded:s}}#de(){if(!(!this.#i||this.#P))for(let e of Object.values(this.#t.uploadGroups)){let t=!1,r=0,s=0,i=0,o=0,a=0,l=0,c=0,u=0,d=0,m=0;for(let A of e.assetIds){let S=this.#t.getUploadAsset(A);if(!S)continue;let y=S.totalBytesToUpload;switch(r+=y,s+=S.bytesUploaded,S.status){case"success":i++,o+=y;break;case"failed":a++,l+=y;break;case"cancelled":c++,u+=y;break;case"in-progress":d++,t=!0;break;case"queued":m++,t=!0;break;case"paused":t=!0;break}}if(!t)continue;let g=this.#x.get(e.id),p=g?Date.now()-g:0;this.#i("upload:group_progress",{group_id:e.id,file_count:e.assetIds.length,total_bytes:r,bytes_uploaded:s,duration_ms:p,project_id:e.projectId,succeeded_count:i,succeeded_bytes:o,failed_count:a,failed_bytes:l,cancelled_count:c,cancelled_bytes:u,in_progress_count:d,queued_count:m,progress:r>0?s/r:0,concurrency:this.#l,upload_speed_mbps:this.#t.uploadStats.uploadSpeedMbps})}}#te(e,t,r){if(!this.#i)return;let{totalBytes:s,bytesUploaded:i}=this.#ee(t);this.#i(r,{file_count:t.fileCount,total_bytes:s,bytes_uploaded:i,project_id:t.projectId})}#ne(e){if(!this.#i)return;let t=this.#t.getUploadAsset(e);if(!t?.groupId)return;let r=this.#t.uploadGroups[t.groupId];if(!r)return;let s=!0,i=0,o=0,a=0,l=0,c=0,u=0,d=0;for(let p of r.assetIds){let A=this.#t.getUploadAsset(p);if(!A)continue;let S=A.totalBytesToUpload;if(d+=S,A.status==="success")i++,o+=S;else if(A.status==="failed")a++,l+=S;else if(A.status==="cancelled")c++,u+=S;else{s=!1;break}}if(!s)return;let m=this.#x.get(r.id),g=m?Date.now()-m:0;this.#i("upload:group_completed",{file_count:r.assetIds.length,total_bytes:d,duration_ms:g,project_id:r.projectId,succeeded_count:i,succeeded_bytes:o,failed_count:a,failed_bytes:l,cancelled_count:c,cancelled_bytes:u}),this.#x.delete(r.id)}#pe(){let e={};for(let t of this.#t.dirtyHistoryGroupIds){let r=this.#t.buildHistoryItem(t);r&&(e[t]=r)}return e}#$(){if(!this.#r)return;let e={};for(let t of this.#t.dirtyHistoryGroupIds){let r=this.#t.buildHistoryItem(t);if(r){e[t]=r;let s=this.#C.findIndex(i=>i.groupId===t);s>=0?this.#C[s]=r:this.#C.unshift(r)}}Object.keys(e).length>0&&this.#r.merge(e)}};var re=class{#e=65536;#n=0;async*createIterator(e,t,r){let s=0,i=Math.max(65536,Math.min(e.byteLength,this.#e)),o=this.#n;for(;s<e.byteLength;){if(r?.aborted)return;let a=t?t.getLimit():null,l=a!==null&&a>0;if(l){let p=Math.round(a*50/1e3);i=Math.max(65536,Math.min(e.byteLength,p))}let c=Math.min(s+i,e.byteLength),u=e.subarray(s,c),d=u.byteLength;if(l&&(await t.acquire(d),r?.aborted))return;let m=performance.now();yield u;let g=performance.now()-m;if(s=c,!l){if(g>=.5){let p=d/g*1e3;o=o===0?p:o*(1-.3)+p*.3}else o===0&&(i=Math.min(e.byteLength,i*2));if(o>0){let p=Math.round(o*50/1e3);i=Math.max(65536,Math.min(e.byteLength,p))}}this.#e=i,this.#n=o}}};var h=(n,e=2)=>{if(n===0)return"0 B";let t=1024,r=e<0?0:e,s=["B","KB","MB","GB","TB","PB","EB"],i=Math.floor(Math.log(n)/Math.log(t));return`${(n/Math.pow(t,i)).toFixed(r)} ${s[i]}`},Re=n=>{if(n===null)return null;let t=n*8/(1024*1024);return t<1?`${(t*1024).toFixed(0)} Kbps`:`${t.toFixed(1)} Mbps`},se=n=>{if(n===null)return null;let e=Math.floor(n/3600),t=Math.floor(n%3600/60),r=Math.floor(n%60);return e>0?`${e}h ${t}m`:t>0?`${t}m ${r}s`:`${r}s`};var sr=1e3,lt=class{#e=null;#n=!1;#t=null;#r=null;#s=null;#i=new Map;#a=null;#c=null;#o=null;#u=null;start(){this.#n||(this.#n=!0,this.#i.clear(),this.#a=null,this.#c=null,this.#o=null,this.#u=null,this.#e=setInterval(()=>this.render(),sr))}stop(){this.#n&&(this.#n=!1,this.#e&&(clearInterval(this.#e),this.#e=null),this.render(),Nt.done())}updateSnapshot(e){this.#t=e}updateBatchState(e){this.#r=e}updateDownloadProgress(e){if(!e){this.#s=null;return}let t=e.percentComplete>=100||e.bytesTransferred>=e.totalBytes;!t&&e.speed>0&&(this.#o=e),this.#s=t&&this.#o?{...e,speed:this.#o.speed,eta:this.#o.eta}:e}persistCurrentBatchLine(){!this.#r||this.#r.currentPhase!=="complete"||this.#i.set(this.#r.currentBatch,this.#y(this.#r))}resetUploadSnapshot(){this.#t=null,this.#s=null,this.#o=null,this.#u=null}render(){if(!this.#n)return;let e=this.#r?this.#U(this.#r):this.#l();Nt(e.join(`
|
|
3
|
-
`))}#p(e,t){let r=[`${f.green(h(t.bytesTransferred))} / ${f.gray(h(t.totalBytes))}`,f.cyan(`${t.percentComplete.toFixed(1)}%`),f.magenta(Re(t.speed)??"..."),`${f.yellow("ETA")}: ${f.yellow(se(t.eta)??"...")}`];return`${f.blue(e)}: ${r.join(" | ")}`}#l(){let e=this.#m();return[this.#P(e),this.#T(e)]}#U(e){let t=[];for(let r=1;r<e.currentBatch;r++){let s=this.#i.get(r);s&&t.push(s)}return t.push(this.#y(e)),t.push(this.#k(e)),t}#y(e){let t=`Batch ${e.currentBatch}/${e.totalBatches}`;switch(e.currentPhase){case"downloading":return this.#s?`${t}: ${this.#p("Downloading",this.#s)}`:`${t}: ${f.blue("Downloading...")}`;case"scanning":return`${t}: ${f.yellow(e.extraDetails??"Scanning...")}`;case"syncing_folders":return`${t}: ${f.yellow(e.extraDetails??"Syncing folders...")}`;case"uploading":return this.#F(t,e);case"cleaning":return`${t}: ${f.yellow("Cleaning...")}`;case"complete":return`${t}: ${f.green("Complete")} (${e.batchFilesTotal} files, ${h(e.batchBytesTotal)}${e.extraDetails?`, ${e.extraDetails}`:""})`}}#F(e,t){let r=this.#m(),s=r.successFileCount+r.failedFileCount+r.cancelledFileCount,i=Math.max(t.batchFilesTotal-t.batchFilesSkipped,0),o=Math.max(t.batchBytesTotal-t.batchBytesSkipped,0),a=o>0?(r.uploadedBytes/o*100).toFixed(1):"0.0",l=this.#R(t,r,o),c=l?.formattedSpeed??null,u=l?.formattedTime??null,d=r.totalFileCount>0&&r.totalFileCount<i?`, ${f.gray(`Enqueued: ${r.totalFileCount}/${i}`)}`:"",m=c&&u?`, ${c}, ETA: ${u}`:"",g=t.batchFilesSkipped>0?`, ${f.yellow(`Skipped: ${t.batchFilesSkipped} files / ${h(t.batchBytesSkipped)}`)}`:"",p=o>0&&r.uploadedBytes>=o&&s<i?"Finalizing":"Uploading";return`${e}: ${f.blue(p)} (${s}/${i} files, ${h(r.uploadedBytes)} / ${h(o)}, ${a}%${d}${m}${g})`}#k(e){let t=this.#m(),r=e.batchFilesSkipped+t.successFileCount+t.failedFileCount+t.cancelledFileCount,s=e.batchBytesSkipped+t.uploadedBytes,i=e.overallFilesCompleted+r,o=e.overallBytesCompleted+s,a=Math.max(e.overallBytesTotal-o,0),l=this.#C(e),c=this.#b(e,t),u=l!==null&&c!==null?l+c:null;return[`Total: ${i}/${e.overallFilesTotal} files`,`${h(o)} / ${h(e.overallBytesTotal)}`,f.yellow(`${h(a)} remaining`),`Download ETA: ${se(l)??"..."}`,`Upload ETA: ${se(c)??"..."}`,`Total ETA: ${se(u)??"..."}`].join(", ")}#C(e){let t=e.overallBytesCompleted+e.batchBytesSkipped+(this.#s?.bytesTransferred??0),r=Math.max(e.overallBytesTotal-t,0);if(r===0)return e.currentPhase==="downloading"&&this.#s?(this.#a=this.#s.eta,this.#s.eta):(this.#a=0,0);if(this.#s&&this.#s.speed>0){let s=Math.ceil(r/this.#s.speed);return this.#a=s,s}return e.currentPhase==="uploading"||e.currentPhase==="cleaning"||e.currentPhase==="complete"?(this.#a=0,0):this.#a}#b(e,t){let r=e.overallBytesCompleted+e.batchBytesSkipped+t.uploadedBytes,s=Math.max(e.overallBytesTotal-r,0),i=Math.max(e.batchBytesTotal-e.batchBytesSkipped,0),o=this.#R(e,t,i);if(s===0)return e.currentPhase==="uploading"&&o?(this.#c=o.timeRemainingSeconds,o.timeRemainingSeconds):(this.#c=0,0);if(o&&o.uploadSpeedMbps>0){let a=o.uploadSpeedMbps*1024*1024/8,l=Math.ceil(s/a);return this.#c=l,l}return this.#c}#R(e,t,r){let s=this.#t?.uploadStats,i=r>0&&t.uploadedBytes>=r;return s&&s.uploadSpeedMbps>0&&s.formattedSpeed!=="Calculating..."&&!i?(this.#u={uploadSpeedMbps:s.uploadSpeedMbps,formattedSpeed:s.formattedSpeed,formattedTime:s.formattedTime,timeRemainingSeconds:s.timeRemainingSeconds},this.#u):e.currentPhase==="uploading"&&i&&this.#u?this.#u:s?{uploadSpeedMbps:s.uploadSpeedMbps,formattedSpeed:s.formattedSpeed,formattedTime:s.formattedTime,timeRemainingSeconds:s.timeRemainingSeconds}:null}#P(e){return[`Total: ${e.totalFileCount}`,f.green(`Success: ${e.successFileCount}`),f.red(`Failed: ${e.failedFileCount}`),f.red(`Cancelled: ${e.cancelledFileCount}`),f.blue(`Active: ${e.activeFileCount}`),f.gray(`Queued: ${e.queuedFileCount}`)].join(" | ")}#T(e){let t=Math.max(e.totalBytes-e.uploadedBytes,0),r=this.#t?` | ${f.cyan(`Speed: ${this.#t.uploadStats.formattedSpeed}`)} | ${f.magenta(`Time remaining: ${this.#t.uploadStats.formattedTime}`)}`:"";return[`Total: ${h(e.totalBytes)}`,f.green(`Uploaded: ${h(e.uploadedBytes)}`),f.yellow(`Remaining: ${h(t)}`)].join(" | ")+r}#m(){return this.#t?Object.values(this.#t.uploadAssets).reduce((t,r)=>{switch(t.totalFileCount+=1,t.totalBytes+=r.totalBytesToUpload,t.uploadedBytes+=r.status==="success"?r.totalBytesToUpload:r.bytesUploaded,r.status){case"success":t.successFileCount+=1;break;case"failed":t.failedFileCount+=1;break;case"cancelled":t.cancelledFileCount+=1;break;case"in-progress":t.activeFileCount+=1;break;default:t.queuedFileCount+=1;break}return t},{totalFileCount:0,successFileCount:0,failedFileCount:0,cancelledFileCount:0,activeFileCount:0,queuedFileCount:0,uploadedBytes:0,totalBytes:0}):{totalFileCount:0,successFileCount:0,failedFileCount:0,cancelledFileCount:0,activeFileCount:0,queuedFileCount:0,uploadedBytes:0,totalBytes:0}}},C=new lt;import{Readable as ir}from"node:stream";import zt from"axios";var x=class{#e;#n;#t;#r;#s=new re;#i=new Set;constructor(e){this.#e=zt.create({baseURL:e.apiUrl}),this.#n=zt.create({baseURL:e.edgeWorkerUrl}),this.#t=e.apiKey,this.#r=e.sessionId}get skippedAssetIds(){return this.#i}async post(e,t,r){let s=await this.#e.post(e,t,{headers:{Authorization:`Bearer ${this.#t}`,"X-Aspect-Session-Id":this.#r,"Content-Type":"application/json",...r}});return this.#c(e,t,s.data),s.data}async get(e,t){return(await this.#e.get(e,{headers:{Authorization:`Bearer ${this.#t}`,"X-Aspect-Session-Id":this.#r,...t}})).data}async delete(e,t){await this.#e.delete(e,{headers:{Authorization:`Bearer ${this.#t}`,"X-Aspect-Session-Id":this.#r,...t}})}async putWithToken(e,t,r,s){let i=await this.#a(t),o=this.#s.createIterator(i,s.limiter??null,s.signal),a=ir.from(o,{highWaterMark:1}),l=await this.#n.put(e,a,{timeout:0,signal:s.signal,headers:{"Content-Type":s.contentType??"","Content-Length":i.byteLength.toString(),Authorization:`Bearer ${r}`},transformRequest:[c=>c],maxRedirects:0,onUploadProgress:c=>s.onProgress?.(c.loaded)});return{status:l.status,statusText:l.statusText,headers:Object.fromEntries(Object.entries(l.headers)),data:l.data,raw:l}}async#a(e){if(e instanceof Uint8Array)return e;let t=await e.arrayBuffer();return new Uint8Array(t)}#c(e,t,r){if(e!=="/assets/chunked/initiate"||!Array.isArray(t)||!Array.isArray(r))return;let s=t;r.forEach((o,a)=>{let l=s[a];o.skipped===!0&&typeof l?.id=="string"&&this.#i.add(l.id)})}};import oe from"node:path";import U from"node:path";function b(n){let e=n.replace(/\\/g,"/");if(e.split("/").some(i=>i===".."))throw new Error(`Remote path cannot contain parent directory segments: ${n}`);let s=U.posix.normalize(e).replace(/^\/+/,"");if(s===""||s===".")throw new Error(`Remote path must resolve to a file path: ${n}`);return s}function Pe(n){let e=new Map;for(let i of n){let o=b(i.targetPath??i.path);e.set(o,(e.get(o)??0)+1)}let t=new Set,r=[],s=[];for(let i of n){let o=b(i.path),a=b(i.targetPath??i.path),l=ie(a),c=ct(l,t),u=(e.get(a)??0)>1,d=c!==o;t.add(c),r.push({...i,targetPath:c,requiresIdentityDownload:i.requiresIdentityDownload===!0||u}),(d||u)&&s.push({sourcePath:i.path,targetPath:c,reason:u||c!==l?"duplicate":"sanitized"})}return{files:r,changes:s}}function w(n){return b(n.targetPath??n.path)}function ke(n,e){let t=w(n);return{relativePath:t,absolutePath:U.join(e,t),fileName:U.posix.basename(t),size:n.size}}function ie(n){return n.split("/").map(t=>$(t)).join("/")}function ct(n,e){if(!e.has(n))return n;let t=U.posix.dirname(n),r=U.posix.basename(n),s=U.posix.extname(r),i=s.length>0?r.slice(0,-s.length):r,o=2;for(;;){let a=`${i} (${o})${s}`,l=t==="."?a:`${t}/${a}`;if(!e.has(l))return l;o+=1}}function ut(n,e){if(!e.has(n))return n;let t=U.posix.dirname(n),r=U.posix.basename(n),s=2;for(;;){let i=`${r} ${s}`,o=t==="."?i:`${t}/${i}`;if(!e.has(o))return o;s+=1}}var $t=500,or=8,Te=class{#e;#n;#t=new Map;constructor(e){this.#e=e.rootDirectoryId,this.#n=e.httpClient}async ensureDirectories(e){await this.loadExistingDirectories();let t=this.#r(e);for(let r of t){if(this.#t.has(r))continue;let s=oe.posix.dirname(r),i=oe.posix.basename(r),o=s==="."?this.#e:this.#t.get(s);if(!o)throw new Error(`Parent directory ID not found for path: ${r}`);let a=await this.#o(o,i);if(a.name!==i)throw new Error(`Server created renamed directory "${a.name}" for planned path "${r}". Refusing to map uploads to an unexpected target path.`);this.#t.set(r,a.id)}return e.map(r=>({file:r,directoryId:this.getDirectoryIdForFile(r.relativePath)}))}async loadExistingDirectories(){let e=await this.#s(this.#e);this.#t.clear(),this.#c(e,"")}getDirectoryIdForFile(e){let t=b(e),r=oe.posix.dirname(t);if(r===".")return this.#e;let s=this.#t.get(r);if(!s)throw new Error(`Directory ID not found for path: ${r}`);return s}getExistingDirectoryIdForFile(e){let t=b(e),r=oe.posix.dirname(t);return r==="."?this.#e:this.#t.get(r)??null}async checkAssetsExistence(e,t=!0){if(e.length===0)return[];let r=[];for(let s=0;s<e.length;s+=$t){let i=e.slice(s,s+$t),o=await this.#n.post("/assets/check-exists-and-uploaded",{items:i,delete_if_not_exist:t});r.push(...o.items)}return r}async listFilesInSubtree(e={}){let t=[{id:this.#e,relativePath:""}],r=[],s=0;for(;s<t.length;){let i=t.slice(s,s+or),o=await Promise.all(i.map(a=>this.#i(a)));s+=i.length;for(let a of o)t.push(...a.directories),r.push(...a.files);e.onProgress?.({scannedDirectoryCount:s,queuedDirectoryCount:t.length,fileCount:r.length})}return r}#r(e){let t=new Set;for(let r of e){let s=b(r.relativePath),i=oe.posix.dirname(s);if(i===".")continue;let o=i.split("/");for(let a=0;a<o.length;a++)t.add(o.slice(0,a+1).join("/"))}return Array.from(t).sort((r,s)=>r.split("/").length-s.split("/").length)}async#s(e){return this.#n.get(`/directories/${e}/tree`)}async#i(e){let[t,r]=await Promise.all([this.#n.post("/fs/list/directories",{parent_id:e.id}),this.#n.post("/fs/list/assets",{parent_id:e.id})]);return{directories:t.map(s=>({id:s.id,relativePath:this.#a(e.relativePath,s.name)})),files:r.map(s=>({assetId:s.id,relativePath:this.#a(e.relativePath,s.name),sizeBytes:s.size_bytes,isUploaded:s.is_uploaded??!0,uploadStateKnown:typeof s.is_uploaded=="boolean"}))}}#a(e,t){let r=e===""?t:`${e}/${t}`;return b(r)}#c(e,t){let r=t===""?"":t==="."?e.name:`${t}/${e.name}`;r!==""&&this.#t.set(r,e.id);for(let s of e.children){let i=t===""?".":r;this.#c(s,i)}}async#o(e,t){return this.#n.post(`/directories/${e}/directories`,{name:t,auto_rename:"numeric"})}};import{PostHog as ar}from"posthog-node";var O=null,ve="",dt={};function Gt(n){O||n.config.analytics.disabled||!n.config.analytics.posthogKey||(ve=n.user.id,dt={service:"data-sync",package_version:n.packageVersion,platform:process.platform,arch:process.arch,node_version:process.version,max_concurrent:n.config.maxConcurrent,batch_mode:n.config.batchSizeBytes!==void 0,batch_size_bytes:n.config.batchSizeBytes??null,source_kind:n.config.source.kind,...n.config.source.kind==="rclone"?{rclone_transfers:n.config.source.rcloneOptions.transfers,rclone_multi_thread_streams:n.config.source.rcloneOptions.multiThreadStreams}:{}},O=new ar(n.config.analytics.posthogKey,{host:n.config.analytics.posthogHost}),O.identify({distinctId:ve,properties:{user_id:n.user.id,email:n.user.email,first_name:n.user.first_name,last_name:n.user.last_name,utm_source_latest:null,utm_medium_latest:null,utm_campaign_latest:null,utm_content_latest:null}}))}function Ht(n,e){O&&O.capture({distinctId:ve,event:n,properties:{...dt,...e}})}async function jt(){let n=O;if(lr(),!!n)try{await n.flush()}catch{}}function lr(){O=null,ve="",dt={}}import{spawn as xe}from"child_process";import*as mt from"fs";import*as ae from"path";var I=class extends Error{constructor(t,r){super(t);this.stderr=r;this.name="RcloneError"}stderr};function cr(n){let e=["sync",n.remoteSource,n.localPath];return n.batchFilePath&&e.push("--files-from",n.batchFilePath),e.push("--progress","--stats","1s","--stats-one-line","-v","--transfers",String(n.rcloneOptions.transfers),"--checkers",String(n.rcloneOptions.checkers),"--multi-thread-streams",String(n.rcloneOptions.multiThreadStreams),"--multi-thread-chunk-size",n.rcloneOptions.multiThreadChunkSize,"--multi-thread-cutoff",n.rcloneOptions.multiThreadCutoff,"--fast-list","--buffer-size",n.rcloneOptions.bufferSize),n.rcloneOptions.useMmap&&e.push("--use-mmap"),n.rcloneOptions.extraRcloneArgs?.length&&e.push(...n.rcloneOptions.extraRcloneArgs),e}function ur(n){let e=["lsjson",n.remoteSource,"--recursive","--fast-list"];return n.extraArgs?.length&&e.push(...n.extraArgs),e}function dr(n){let e=["backend","query",`${n.remote}:`,n.query];return n.extraArgs?.length&&e.push(...n.extraArgs),e}function pr(n){let e=["copyto",n.remoteFileSource,n.localTargetPath,"--progress","--stats","1s","--stats-one-line","-v","--multi-thread-streams",String(n.rcloneOptions.multiThreadStreams),"--multi-thread-chunk-size",n.rcloneOptions.multiThreadChunkSize,"--multi-thread-cutoff",n.rcloneOptions.multiThreadCutoff,"--buffer-size",n.rcloneOptions.bufferSize];return n.rcloneOptions.useMmap&&e.push("--use-mmap"),n.rcloneOptions.extraRcloneArgs?.length&&e.push(...n.rcloneOptions.extraRcloneArgs),e}function mr(n){let e=["backend","copyid",`${n.remote}:`,n.fileId,n.localTargetPath];return n.rcloneOptions.extraRcloneArgs?.length&&e.push(...n.rcloneOptions.extraRcloneArgs),e}function G(n,e){let t=e.trim(),r={B:1,k:1024,Ki:1024,KiB:1024,kB:1e3,M:1024*1024,Mi:1024*1024,MiB:1024*1024,MB:1e3*1e3,G:1024*1024*1024,Gi:1024*1024*1024,GiB:1024*1024*1024,GB:1e3*1e3*1e3,T:1024*1024*1024*1024,Ti:1024*1024*1024*1024,TiB:1024*1024*1024*1024,TB:1e3*1e3*1e3*1e3};return n*(r[t]||1)}function Wt(n){let e=0,t=n.match(/(\d+)h/),r=n.match(/(\d+)m/),s=n.match(/(\d+)s/);return t&&(e+=parseInt(t[1],10)*3600),r&&(e+=parseInt(r[1],10)*60),s&&(e+=parseInt(s[1],10)),e}function hr(n){let e=n.trim(),t=/^([\d.]+)\s*([A-Za-z]+)\s*\/\s*([\d.]+)\s*([A-Za-z]+),\s*([\d.]+)%?,\s*([\d.]+)\s*([A-Za-z]+)\/s,\s*ETA\s+(.+)$/,r=e.match(t);if(r){let a=r[8].trim();return{bytesTransferred:G(parseFloat(r[1]),r[2]),totalBytes:G(parseFloat(r[3]),r[4]),percentComplete:parseFloat(r[5]),speed:G(parseFloat(r[6]),r[7]),eta:a==="-"?0:Wt(a)}}let s=e.match(/Transferred:\s+([\d.]+)\s*([A-Za-z]+)\s*\/\s*([\d.]+)\s*([A-Za-z]+),\s*([\d.]+)%/);if(!s)return null;let i=e.match(/([\d.]+)\s*([A-Za-z]+)\/s/),o=e.match(/ETA\s+([^\s]+)$/);return{bytesTransferred:G(parseFloat(s[1]),s[2]),totalBytes:G(parseFloat(s[3]),s[4]),percentComplete:parseFloat(s[5]),speed:i?G(parseFloat(i[1]),i[2]):0,eta:o&&o[1]!=="-"?Wt(o[1]):0}}function pt(n){return new Promise((e,t)=>{let r=xe("rclone",n.args,{stdio:["ignore","pipe","pipe"]}),s="",i=0,o=a=>{for(let l of a.split(`
|
|
4
|
-
`)){if(l.trim().length===0)continue;let c=hr(l);if(!c)continue;let u=Date.now();!(c.percentComplete>=100)&&u-i<500||(i=u,n.onProgress?.(c))}};r.stdout.on("data",a=>{o(a.toString())}),r.stderr.on("data",a=>{let l=a.toString();s+=l,o(l)}),r.on("close",async a=>{a===0?e():t(new I(`rclone exited with code ${a}`,s))}),r.on("error",a=>{t(new I(`Failed to start rclone: ${a.message}`,""))})})}async function Ue(){return new Promise((n,e)=>{let t=xe("rclone",["version"]);t.on("error",()=>{e(new Error("rclone is not installed or not in PATH. Please install rclone first: https://rclone.org/install/"))}),t.on("close",r=>{r===0?n():e(new Error("rclone is not installed or not in PATH. Please install rclone first: https://rclone.org/install/"))})})}async function fr(n,e,t,r,s,i){let o=`${n}:${e}`;return pt({args:cr({remoteSource:o,localPath:t,rcloneOptions:s,batchFilePath:r}),remoteSource:o,onProgress:i})}async function qt(n,e,t=[]){let r=`${n}:${e}`;return new Promise((s,i)=>{let o=xe("rclone",ur({remoteSource:r,extraArgs:t})),a="",l="";o.stdout.on("data",c=>{a+=c.toString()}),o.stderr.on("data",c=>{l+=c.toString()}),o.on("close",async c=>{if(c===0)try{let u=JSON.parse(a||"[]");if(!Array.isArray(u))throw new Error("rclone lsjson did not return an array");let d=gr(u),m=await yr({remote:n,files:d.files,directories:d.directories,extraArgs:t});s(m)}catch(u){i(new I(`Failed to parse file listing from ${r}: ${u instanceof Error?u.message:String(u)}`,l))}else i(new I(`Failed to list files from ${r}`,l))}),o.on("error",c=>{i(new I(`Failed to start rclone: ${c.message}`,""))})})}async function Kt(n){let e=[],t=[];for(let r of n.files)wr(r)?t.push(r):e.push(r);e.length>0&&(await mt.promises.writeFile(n.batchFilePath,`${e.map(r=>r.path).join(`
|
|
2
|
+
import{Command as qo}from"commander";import or from"node:path";import{readFileSync as Jo,realpathSync as sr}from"node:fs";import{fileURLToPath as Yo}from"node:url";import ge from"node:fs/promises";import Lt from"node:path";import cr from"fs/promises";import ur from"path";function Kt(n,e){let t=new Map;for(let c of n){let u=ur.dirname(c.targetPath??c.path);t.has(u)||t.set(u,[]),t.get(u).push(c)}let r=new Map;for(let[c,u]of t.entries()){let d=u.reduce((m,f)=>m+f.size,0);r.set(c,d)}let s=Array.from(t.keys()).sort(),o=[],i=[],a=0,l=1;for(let c of s){let u=t.get(c),d=r.get(c);if(d>e){if(i.length>0&&(o.push({batchNumber:l++,files:i,totalSize:a}),i=[],a=0),u.length===1)o.push({batchNumber:l++,files:u,totalSize:d});else for(let m of u)a+m.size>e&&i.length>0&&(o.push({batchNumber:l++,files:i,totalSize:a}),i=[],a=0),i.push(m),a+=m.size;continue}a+d>e&&i.length>0&&(o.push({batchNumber:l++,files:i,totalSize:a}),i=[],a=0),i.push(...u),a+=d}return i.length>0&&o.push({batchNumber:l++,files:i,totalSize:a}),o}async function qt(n){try{await cr.unlink(n)}catch(e){if(e.code!=="ENOENT")throw e}}import{Readable as Pr}from"node:stream";import Xt from"axios";function ne(n,e){if(e.length===0)return n.finalizedStatus?n.finalizedStatus:n.isCreatingFolders?"creating-folders":"queued";if(n.isCreatingFolders)return"creating-folders";let t={queued:0,paused:0,inProgress:0,success:0,failed:0,cancelled:0};for(let s of e)switch(s.status){case"queued":t.queued++;break;case"paused":t.paused++;break;case"in-progress":t.inProgress++;break;case"success":t.success++;break;case"failed":t.failed++;break;case"cancelled":t.cancelled++;break}let r=e.length;return t.failed===r?"all-failed":t.failed>0?"some-failed":t.success===r?"success":t.paused>0&&t.queued===0&&t.inProgress===0?"paused":t.queued>0||t.inProgress>0?t.queued+t.paused===r?"queued":"in-progress":"cancelled"}function it(n,e){let t=ne(n,e);return t==="creating-folders"||t==="in-progress"||t==="queued"||t==="paused"?"cancelled":t}function at(n){let e=[];for(let t of Object.values(n))t.chunkedState&&(t.status==="queued"||t.status==="in-progress"||t.status==="paused")&&e.push(t.chunkedState.assetId);return e}function lt(n){for(let e of Object.values(n))if(e.status==="queued"||e.status==="in-progress"||e.status==="paused")return!0;return!1}function re(n){let t=Object.values(n).reduce((r,s)=>{switch(s.status!=="failed"&&s.status!=="cancelled"&&(r.totalBytesToUpload+=s.totalBytesToUpload,r.totalBytesUploaded+=s.bytesUploaded),r.totalAssetCount+=1,s.status){case"queued":r.queuedAssetCount+=1;break;case"paused":r.pausedAssetCount+=1;break;case"in-progress":r.inProgressAssetCount+=1;break;case"success":r.successAssetCount+=1;break;case"failed":r.failedAssetCount+=1;break;case"cancelled":r.cancelledAssetCount+=1;break}return r},{totalBytesToUpload:0,totalBytesUploaded:0,totalAssetCount:0,queuedAssetCount:0,pausedAssetCount:0,inProgressAssetCount:0,successAssetCount:0,failedAssetCount:0,cancelledAssetCount:0,hasActiveUploads:!1,progress:0});return t.hasActiveUploads=t.totalAssetCount-t.successAssetCount-t.failedAssetCount-t.cancelledAssetCount>0,t.progress=t.hasActiveUploads?t.totalBytesUploaded/t.totalBytesToUpload:0,t}function Pe(n,e){if(e.length===0)return null;let t=e.reduce((r,s)=>(s.status!=="failed"&&s.status!=="cancelled"&&(r.totalBytes+=s.totalBytesToUpload,r.uploadedBytes+=s.bytesUploaded),s.status==="success"?r.filesSucceeded++:s.status==="failed"&&r.filesFailed++,(s.status==="success"||s.status==="failed"||s.status==="cancelled")&&r.filesCompleted++,r),{totalBytes:0,uploadedBytes:0,filesCompleted:0,filesSucceeded:0,filesTotal:e.length,filesFailed:0,percentage:0});return t.percentage=t.totalBytes>0?t.uploadedBytes/t.totalBytes*100:0,t}function ct(n){let e=Object.values(n).filter(t=>t.status==="queued"||t.status==="in-progress"||t.status==="paused");return e.length===0?!1:e.every(t=>t.status==="paused")}function ut(n){return Object.values(n).some(e=>e.status==="paused")}import pi from"axios";var se=class{#e;#s;#t;#o;#r;#n=0;#i=0;#c=0;#l=0;#u=0;#p=0;constructor(e){this.#e=e?.alphaFast??.1,this.#s=e?.alphaMax??.5,this.#t=e?.consecutiveForBoost??3,this.#o=e?.minSamples??3,this.#r=e?.maxGapSeconds??2}sample(e){let t=Date.now();if(this.#l===0){this.#l=t,this.#u=e;return}let s=(t-this.#l)/1e3,o=e-this.#u;if(s<=0||o<0)return;if(s>this.#r){this.#l=t,this.#u=e;return}let i=o/s;if(this.#p===0)this.#n=i;else{let l=i-this.#n>=0?1:-1;this.#c!==0&&l===this.#c?this.#i++:this.#i=0,this.#c=l;let c=Math.min(1,this.#i/this.#t),u=this.#e+(this.#s-this.#e)*c;this.#n=u*i+(1-u)*this.#n}this.#l=t,this.#u=e,this.#p++}etaSeconds(e){return!this.isWarmedUp||this.#n<=0?0:e/this.#n}adjustTotalBytes(e){this.#u+=e}reset(){this.#n=0,this.#i=0,this.#c=0,this.#l=0,this.#u=0,this.#p=0}serialize(){return{displaySpeedBps:this.#n,lastSampleTimestamp:this.#l,lastSampleTotalBytes:this.#u,sampleCount:this.#p}}get speedBps(){return this.#n}get speedMbps(){return this.#n*8/1e6}get isWarmedUp(){return this.#p>=this.#o}};function O(n){let e={"X-Aspect-Share-Id":n.shareId};return n.shareAuthentication&&(e["X-Aspect-Share-Authentication"]=n.shareAuthentication),e}var oe=class{#e;#s;#t;#o;#r;#n;#i;#c;#l;#u;#p;#a;#k;#g;#I;#P;#C;#h;#b;#E;#R;#m;#y;#T;#d;#v;#f;#w;#L;#B;#D;#M;constructor(e){this.#s=e?.minConcurrency??1,this.#t=e?.maxConcurrency??8,this.#e=this.#j(e?.initialConcurrency??this.#s),this.#o=e?.errorThreshold??1,this.#r=(e?.cooldownSeconds??10)*1e3,this.#n=e?.plateauThreshold??.05,this.#i=Math.max(this.#t,Math.floor(e?.sampleWindowSize??64)),this.#c=Math.max(2,Math.floor(e?.minSamples??4)),this.#l=Math.max(1.1,e?.increaseFactor??1.5),this.#u=e?.onChange,this.#p=e?.now??Date.now,this.#a=this.#e,this.#k=0,this.#g=[],this.#I=0,this.#P=0,this.#C=-1,this.#h=0,this.#b=void 0,this.#E=0,this.#R=0,this.#m=0,this.#y=this.#a,this.#T=0,this.#d=1/0,this.#v=0,this.#f=6e4,this.#w=0,this.#L=1/0,this.#B=0,this.#D=0,this.#M=0}recordSuccess(e,t,r){if(e<=0)return;if(r?.generation!==void 0){if(r.generation!==this.#k){r.generation===this.#C&&this.#h>0&&(this.#h--,this.#h===0&&(this.#b=r.completedAtMs??this.#p()));return}if(this.#h>0||this.#b!==void 0&&r.startedAtMs!==void 0&&r.startedAtMs<this.#b)return}else if(this.#P>0){this.#P--;return}let s=r?.completedAtMs??this.#p();for(this.#g.push({bytes:e,completedAtMs:s,startedAtMs:r?.startedAtMs,durationMs:t!==void 0&&t>0?t:void 0});this.#g.length>this.#i;)this.#g.shift();this.#I++,this.#E=0;let o=this.#z();this.#D=o.throughputBps,this.#M=o.latencyMsPerMB,this.#x(o)}recordError(){if(this.#E++,this.#E<this.#o)return;let e=this.#a;e===this.#w&&(this.#L=Math.min(this.#L,e),this.#B=this.#p()+3e4),this.#w=e;let t=this.#j(Math.floor(e/2));this.#R=this.#p()+this.#r,this.#E=0,e<=this.#y&&(this.#y=t,this.#T=0),e>t&&(this.#d=Math.min(this.#d,e),this.#W()),this.#A(t)}get concurrency(){return this.#a}get generation(){return this.#k}get speedBps(){return this.#D}get latencyMsPerMB(){return this.#M}reset(){this.#a=this.#e,this.#k++,this.#g=[],this.#I=0,this.#P=0,this.#C=-1,this.#h=0,this.#b=void 0,this.#E=0,this.#R=0,this.#m=0,this.#y=this.#a,this.#T=0,this.#d=1/0,this.#v=0,this.#f=6e4,this.#w=0,this.#L=1/0,this.#B=0,this.#D=0,this.#M=0,this.#u?.(this.#a)}#x(e){if(this.#g.length<this.#K()||this.#I<this.#K()||e.throughputBps<=0)return;let t=this.#p();if(t<this.#R)return;if(e.averageDurationMs>=2e4&&this.#a>=4){this.#y=Math.max(this.#s,Math.floor(this.#a/2)),this.#T=0,this.#A(this.#y);return}if(this.#T===0){this.#N(e.throughputBps),this.#_(e);return}let r=(e.throughputBps-this.#T)/this.#T;if(r>=this.#n){this.#N(e.throughputBps),this.#_(e);return}if(this.#a>this.#y){let s=r<=-.08,o=r<this.#n;(s||o)&&(this.#d=Math.min(this.#d,this.#a),this.#W(),this.#A(this.#y));return}if(this.#a<this.#y){this.#_(e);return}this.#a===this.#y&&(this.#T=Math.max(this.#T,e.throughputBps),t>=this.#m&&this.#_(e))}#_(e){let t=this.#Y();if(this.#a>=t){this.#I=0;return}if(e.averageDurationMs>=5e3&&this.#a>=4&&this.#T>0){this.#I=0;return}if(this.#U()){let s=this.#p();if(this.#v===0){this.#v=s+this.#f,this.#m=this.#v,this.#I=0;return}if(s<this.#v){this.#I=0;return}}let r=this.#S(t);if(r===this.#a){this.#I=0;return}this.#A(r)}#N(e){this.#y=this.#a,this.#T=e,this.#d<=this.#a&&(this.#d=1/0),this.#v=0,this.#f=6e4,this.#m=0}#S(e){if(this.#d<1/0){let s=Math.floor((this.#a+this.#d)/2);return s>this.#a&&s<this.#d?Math.min(e,s):Math.min(e,this.#a+1)}if(this.#a<4)return Math.min(e,this.#a+1);let t=Math.ceil(this.#a*this.#l),r=this.#a+2;return Math.min(e,Math.max(r,t))}#A(e){let t=this.#a,r=this.#k,s=this.#j(e);s!==t&&(this.#O(),this.#a=s,this.#k++,this.#C=r,this.#h=Math.max(0,t-1),this.#b=this.#h===0?this.#p():void 0,this.#P=Math.max(0,t-1),this.#u?.(this.#a))}#O(){this.#g=[],this.#I=0,this.#P=0}#U(){return this.#d<1/0&&this.#a===this.#y&&this.#d<=this.#y+1}#W(){let e=this.#d<1/0&&this.#d<=this.#y+1,t=e?this.#f:1e4;this.#m=this.#p()+t,e&&(this.#v=this.#m,this.#f=Math.min(this.#f*2,3e5))}#K(){return Math.max(this.#c,this.#a)}#Y(){return this.#L<1/0&&this.#p()>=this.#B&&(this.#L=1/0,this.#B=0),Math.max(this.#s,Math.min(this.#t,this.#L-1))}#j(e){return Math.max(this.#s,Math.min(this.#t,e))}#z(){let e=0,t=0,r=0,s=0;for(let l of this.#g)e+=l.bytes,l.durationMs!==void 0&&(t+=l.durationMs,r++,s+=l.durationMs/(l.bytes/(1024*1024)));if(r>0&&t>0)return{throughputBps:e/(t/1e3)*this.#a,latencyMsPerMB:s/r,averageDurationMs:t/r,durationSampleCount:r};if(this.#g.length<2)return{throughputBps:0,latencyMsPerMB:0,averageDurationMs:0,durationSampleCount:0};let o=this.#g[0],a=this.#g[this.#g.length-1].completedAtMs-o.completedAtMs;return{throughputBps:a>0?e/a*1e3:0,latencyMsPerMB:0,averageDurationMs:a>0?a/Math.max(1,this.#g.length-1):0,durationSampleCount:0}}};var j=class{#e;#s;#t;#o;#r;constructor(e){let t=e===0?null:e;this.#e=t,this.#s=t??0,this.#t=Date.now(),this.#o=[],this.#r=null}setLimit(e){let t=e===0?null:e;if(t===null){this.#e=null,this.#s=0,this.#u();let s=this.#o.splice(0);for(let o of s)o.resolve();return}let r=this.#e;this.#e=t,r===null?(this.#s=t,this.#t=Date.now()):(this.#n(),this.#s=Math.min(this.#s,t)),this.#l()}getLimit(){return this.#e}acquire(e){if(this.#e!==null){if(this.#n(),this.#o.length===0&&this.#s>=e){this.#s-=e;return}return this.#i(e)}}#n(){let e=Date.now(),t=(e-this.#t)/1e3;if(t<=0)return;let r=this.#e,s=t*r,o=this.#o.length>0?Math.max(r,this.#o[0].bytes):r;this.#s=Math.min(this.#s+s,o),this.#t=e}#i(e){return new Promise(t=>{this.#o.push({bytes:e,resolve:t}),this.#r===null&&this.#c()})}#c(){if(this.#o.length===0||this.#e===null){this.#r=null;return}let t=this.#o[0].bytes-this.#s,r=t>0?Math.ceil(t/this.#e*1e3):0;if(r<=0){this.#r=null,this.#l();return}this.#r=setTimeout(()=>{this.#r=null,this.#n(),this.#l()},r)}#l(){for(;this.#o.length>0;){if(this.#e===null){let t=this.#o.splice(0);for(let r of t)r.resolve();return}this.#n();let e=this.#o[0];if(this.#s>=e.bytes)this.#s-=e.bytes,this.#o.shift(),e.resolve();else{this.#c();return}}}#u(){this.#r!==null&&(clearTimeout(this.#r),this.#r=null)}};function Jt(n){let e=`[${n}]`;return{info:(...t)=>console.info(e,...t),warn:(...t)=>console.warn(e,...t),error:(...t)=>console.error(e,...t)}}var dt=Jt("transfer");var Qt="transportDiagnostics";function B(n){return typeof n=="string"&&n.length>0?n:null}function Yt(n){if(n===null||typeof n!="object")return null;let e=n,t=B(e.O),r=B(e.CN),s=[t,r].filter(o=>o!==null);return s.length>0?s.join(" / "):null}function dr(n){if(!n)return{};let e={remoteAddress:B(n.remoteAddress),remoteFamily:B(n.remoteFamily),tlsAuthorized:typeof n.authorized=="boolean"?n.authorized:null};if(typeof n.getProtocol=="function"&&(e.tlsProtocol=B(n.getProtocol())),typeof n.getCipher=="function"){let t=n.getCipher();t!==null&&typeof t=="object"&&(e.tlsCipher=B(t.name))}if(typeof n.getPeerCertificate=="function"){let t=n.getPeerCertificate();if(t!==null&&typeof t=="object"){let r=t;e.peerCertIssuer=Yt(r.issuer),e.peerCertSubject=Yt(r.subject)}}return e}function pt(n){let e={errorCode:null,hadResponse:!1,reusedSocket:null,remoteAddress:null,remoteFamily:null,tlsProtocol:null,tlsCipher:null,peerCertIssuer:null,peerCertSubject:null,tlsAuthorized:null};if(n===null||typeof n!="object")return e;let t=n;e.errorCode=B(t.code),e.hadResponse=t.response!=null;let r=t.request;if(r){e.reusedSocket=typeof r.reusedSocket=="boolean"?r.reusedSocket:null;let s=r.socket??r.res?.socket??null;Object.assign(e,dr(s))}return e}function mt(n,e){n===null||typeof n!="object"||(n[Qt]=e)}function ht(n){if(n===null||typeof n!="object")return null;let e=n[Qt];return e??null}var ft=n=>!Number.isFinite(n)||n<=0?"Calculating...":n<1?`${(n*1e3).toFixed(0)} Kbps`:`${n.toFixed(1)} Mbps`,gt=n=>{if(!Number.isFinite(n)||n<=0)return"Calculating...";let e=Math.floor(n/3600),t=Math.floor(n%3600/60),r=Math.floor(n%60);return e>0?`${e}h ${t}m left`:t>0?`${t}m ${r}s left`:`${r}s left`};var Re=class{uploadAssets={};uploadGroups={};#e=new se;get uploadSpeedState(){return this.#e.serialize()}uploadStats={uploadSpeedMbps:0,timeRemainingSeconds:0,formattedSpeed:"Calculating...",formattedTime:"Calculating..."};dirtyAssetIds=new Set;dirtyGroupIds=new Set;dirtyHistoryGroupIds=new Set;#s(e){e!==0&&this.#e.adjustTotalBytes(-e)}adjustSpeedBaselineForSkippedBytes(e){e!==0&&this.#e.adjustTotalBytes(e)}#t(){Object.values(this.uploadAssets).some(t=>t.status==="queued"||t.status==="in-progress")||this.#e.reset()}#o(e){this.dirtyAssetIds.add(e)}#r(e){this.dirtyGroupIds.add(e)}addUploadAsset({assetId:e,fileReader:t,abortController:r,parentId:s,projectId:o,groupId:i,chunkSize:a,shareContext:l}){this.uploadAssets[e]={assetId:e,totalBytesToUpload:t.size,bytesUploaded:0,status:"queued",fileName:t.name,createdAt:new Date().toISOString(),i:Object.keys(this.uploadAssets).length,parentId:s,projectId:o,groupId:i,retryCount:0,chunkSize:a??0,fileReader:t,abortController:r,shareContext:l},this.#o(e)}updateUploadProgress(e,t){let r=this.uploadAssets[e];if(!r||r.status==="paused"||r.status==="cancelled"||r.status==="success"||r.status==="failed")return;let s=t>0&&r.status==="queued"?"in-progress":r.status,o=Math.min(t,r.totalBytesToUpload);r.bytesUploaded=o,r.status=s,this.#o(e)}markUploadInProgress(e){let t=this.uploadAssets[e];t&&(t.status="in-progress",this.#o(e))}markUploadSuccess(e){let t=this.uploadAssets[e];t&&(t.status="success",t.bytesUploaded=t.totalBytesToUpload,this.#o(e),this.#t(),this.cleanupOnCompletion(e))}markUploadFailed(e,t){let r=this.uploadAssets[e];if(!r)return;let s=r.bytesUploaded;r.status="failed",r.errorMessage=t,r.bytesUploaded=0,this.#o(e),this.#s(s),this.#t(),this.cleanupOnCompletion(e)}removeUploadAsset(e){let r=this.uploadAssets[e]?.bytesUploaded??0;delete this.uploadAssets[e],this.#o(e),this.#s(r),this.#t()}clearAllUploads(){this.uploadAssets={},this.#e.reset()}clearTerminalState(){if(!Object.values(this.uploadAssets).some(t=>t.status==="queued"||t.status==="in-progress"||t.status==="paused")){for(let t of Object.keys(this.uploadAssets))delete this.uploadAssets[t];for(let t of Object.keys(this.uploadGroups))delete this.uploadGroups[t];this.#e.reset()}}resetAssetForRetryQueue(e){let t=this.uploadAssets[e];t&&(t.status="queued",t.bytesUploaded=0,t.errorMessage=void 0,t.retryCount=t.retryCount+1,this.#o(e))}resetAssetForRetrying(e){let t=this.uploadAssets[e];t&&(t.status="queued",t.bytesUploaded=0,t.retryCount=0,this.#o(e))}pauseUpload(e){let t=this.uploadAssets[e];if(!t||t.status!=="queued"&&t.status!=="in-progress")return;let r=0;if(t.chunkedState){let{completedChunkIndices:o,chunkSize:i}=t.chunkedState;for(let a of o){let l=a*i,c=Math.min(l+i,t.totalBytesToUpload);r+=c-l}}let s=t.bytesUploaded-r;t.status="paused",t.bytesUploaded=r,this.#o(e),this.#s(s),this.#t(),t.abortController.abort()}unpauseUpload(e){let t=this.uploadAssets[e];t&&t.status==="paused"&&(t.status="queued",this.#o(e))}pauseUploadGroup(e){let t=this.uploadGroups[e];if(t&&!t.isCreatingFolders){t.isPaused=!0,this.#r(e);for(let r of t.assetIds)this.pauseUpload(r)}}unpauseUploadGroup(e){let t=this.uploadGroups[e];t&&(t.isPaused=!1,this.#r(e))}pauseAllUploads(){for(let e of Object.values(this.uploadGroups))e.isCreatingFolders||this.pauseUploadGroup(e.id)}resumeAllUploads(){for(let e of Object.values(this.uploadGroups))e.isPaused&&this.unpauseUploadGroup(e.id)}markUploadCancelled(e){let t=this.uploadAssets[e];if(!t||t.status==="success"||t.status==="failed"||t.status==="cancelled")return;let r=t.bytesUploaded;t.status="cancelled",this.#o(e),this.#s(r),this.#t(),this.cleanupOnCompletion(e)}setChunkedState(e,t){let r=this.uploadAssets[e];r&&(r.chunkedState=t,this.#o(e))}addCompletedChunkIndex(e,t){let r=this.uploadAssets[e];!r||!r.chunkedState||(r.chunkedState={...r.chunkedState,completedChunkIndices:[...r.chunkedState.completedChunkIndices,t]},this.#o(e))}clearChunkedState(e){let t=this.uploadAssets[e];t&&(t.chunkedState=void 0,this.#o(e))}hasGroupsCreatingFolders(){return Object.values(this.uploadGroups).some(e=>e.isCreatingFolders===!0)}areAllUploadsPaused(){return ct(this.uploadAssets)}hasPausedUploads(){return ut(this.uploadAssets)}getUploadAsset(e){return this.uploadAssets[e]}getSerializableAsset(e){let t=this.uploadAssets[e];if(t)return this.#n(t)}getUploadSummary(){return re(this.#c())}getAllUploadAssetsSortedByRecent(){return Object.values(this.uploadAssets).map(e=>this.#n(e)).sort((e,t)=>t.i-e.i)}getGroupAssets(e){let t=this.uploadGroups[e];return!t||!t.assetIds?[]:t.assetIds.map(r=>this.uploadAssets[r]).filter(Boolean).map(r=>this.#n(r))}getGroupAssetsInternal(e){let t=this.uploadGroups[e];return!t||!t.assetIds?[]:t.assetIds.map(r=>this.uploadAssets[r]).filter(Boolean)}addUploadGroup(e){let t=crypto.randomUUID();return this.uploadGroups[t]={...e,id:t,fileReaders:new Map},this.#r(t),t}updateUploadGroup(e,t){let r=this.uploadGroups[e];r&&(Object.assign(r,t),this.#r(e))}addAssetToGroup(e,t){let r=this.uploadGroups[e];r&&(r.assetIds.push(t),this.#r(e))}finalizeEmptyGroup({groupId:e,status:t,errorMessage:r}){let s=this.uploadGroups[e];s&&(s.assetIds.length>0||s.finalizedStatus||(s.finalizedStatus=t,s.errorMessage=r,s.isCreatingFolders=!1,s.completedAt=new Date().toISOString(),this.#r(e),this.dirtyHistoryGroupIds.add(e)))}removeUploadGroup(e){let t=this.uploadGroups[e];if(t)for(let r of t.assetIds)delete this.uploadAssets[r],this.#o(r);delete this.uploadGroups[e],this.#r(e)}getUploadGroup(e){let t=this.uploadGroups[e];if(t)return this.#i(t)}getAllUploadGroups(){return Object.values(this.uploadGroups).map(e=>this.#i(e)).sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}getUploadGroupProgress(e){let t=this.uploadGroups[e];if(!t)return null;let r=this.getGroupAssets(e);return Pe(this.#i(t),r)}getUploadGroupStatus(e){let t=this.uploadGroups[e];if(!t)return null;let r=this.getGroupAssets(e);return ne(this.#i(t),r)}getAssetsByParentId(e){return Object.values(this.uploadAssets).filter(t=>t.parentId===e).map(t=>this.#n(t))}getActiveUploadGroups(){return Object.values(this.uploadGroups).filter(e=>{let t=this.getUploadGroupStatus(e.id);return t&&["queued","creating-folders","in-progress"].includes(t)}).map(e=>this.#i(e))}cleanupOnCompletion(e){let t=this.uploadAssets[e];if(!t)return;let r=t.groupId;if(r){let o=this.uploadGroups[r];if(o){let i=this.getGroupAssets(r),a=this.#i(o);this.dirtyHistoryGroupIds.add(r),!i.some(c=>c.status==="queued"||c.status==="in-progress")&&!o.completedAt&&(o.completedAt=new Date().toISOString(),this.#r(r))}}let s=this.getUploadSummary();if(s.cancelledAssetCount+s.failedAssetCount+s.successAssetCount===s.totalAssetCount)for(let o of Object.keys(this.uploadAssets)){let i=this.uploadAssets[o];i&&(i.bytesUploaded=0,this.#o(o))}}updateUploadStats(){let e=this.getUploadSummary(),t=e.queuedAssetCount>0||e.inProgressAssetCount>0;t&&this.#e.sample(e.totalBytesUploaded);let r=this.#e.isWarmedUp?this.#e.speedMbps:0,s=t&&this.#e.isWarmedUp?this.#e.etaSeconds(e.totalBytesToUpload-e.totalBytesUploaded):0;this.uploadStats={uploadSpeedMbps:r,timeRemainingSeconds:s,formattedSpeed:ft(r),formattedTime:gt(s)}}buildHistoryItem(e){let t=this.uploadGroups[e];if(!t)return null;let r=this.getGroupAssets(e),s=this.#i(t);return{groupId:t.id,name:t.name,type:t.type,fileCount:t.fileCount,folderCount:t.folderCount,topLevelFileCount:t.topLevelFileCount,topLevelFolderCount:t.topLevelFolderCount,status:it(s,r),createdAt:t.createdAt,completedAt:t.completedAt,rootDirectoryId:t.rootDirectoryId,projectId:t.projectId,errorMessage:t.errorMessage,conflictResolution:t.conflictResolution}}#n({fileReader:e,abortController:t,shareContext:r,...s}){return s}#i({fileReaders:e,...t}){return t}#c(){let e={};for(let[t,r]of Object.entries(this.uploadAssets))e[t]=this.#n(r);return e}#l(){let e={};for(let[t,r]of Object.entries(this.uploadGroups))e[t]=this.#i(r);return e}getSerializableSnapshot(){return{uploadAssets:this.#c(),uploadGroups:this.#l(),uploadStats:{...this.uploadStats},uploadSpeedState:this.uploadSpeedState}}getDirtyDelta(){let e={};for(let r of this.dirtyAssetIds){let s=this.uploadAssets[r];s&&(e[r]=this.#n(s))}let t={};for(let r of this.dirtyGroupIds){let s=this.uploadGroups[r];s&&(t[r]=this.#i(s))}return{assets:e,groups:t}}clearDirtyFlags(){this.dirtyAssetIds.clear(),this.dirtyGroupIds.clear(),this.dirtyHistoryGroupIds.clear()}};function mr(n,e){let t=new Date(n).getTime(),r=Date.now();return t-r<=e}var Te=class{#e;#s=new Map;#t=new Map;constructor(e){this.#e=e}seedToken(e,t,r){this.#s.set(e,{token:t,expiresAt:r})}async getToken(e,t){let r=this.#s.get(e);if(r&&!mr(r.expiresAt,3e5))return r.token;let s=this.#t.get(e);if(s)return s;let o=t?O(t):void 0,i=this.#e.post(`/assets/${e}/token`,{},o).then(a=>{if(!a.token)throw new Error("Token refresh failed: no token in response");return this.#s.set(e,{token:a.token,expiresAt:a.token_expires_at}),this.#t.delete(e),a.token}).catch(a=>{throw this.#t.delete(e),a});return this.#t.set(e,i),i}clearCache(e){e?this.#s.delete(e):this.#s.clear()}};var ke=class{#e=[];registerAsset(e){this.#e.push({assetId:e.assetId,totalChunks:e.totalChunks,nextChunkToClaim:0,completedChunkIndices:new Set(e.completedChunkIndices),isPaused:!1})}claimNextChunk(){for(let e of this.#e)if(!e.isPaused)for(;e.nextChunkToClaim<e.totalChunks;){let t=e.nextChunkToClaim;if(e.nextChunkToClaim++,!e.completedChunkIndices.has(t))return{assetId:e.assetId,chunkIndex:t}}return null}markChunkCompleted(e,t){let r=this.#s(e);return r?(r.completedChunkIndices.add(t),r.completedChunkIndices.size>=r.totalChunks):!1}pauseAsset(e){let t=this.#s(e);t&&(t.isPaused=!0)}unpauseAsset(e){let t=this.#s(e);t&&(t.isPaused=!1,this.#t(t))}removeAsset(e){this.#e=this.#e.filter(t=>t.assetId!==e)}hasAsset(e){return this.#e.some(t=>t.assetId===e)}isAssetComplete(e){let t=this.#s(e);return t?t.completedChunkIndices.size>=t.totalChunks:!1}clear(){this.#e=[]}#s(e){return this.#e.find(t=>t.assetId===e)}#t(e){for(let t=0;t<e.totalChunks;t++)if(!e.completedChunkIndices.has(t)){e.nextChunkToClaim=t;return}e.nextChunkToClaim=e.totalChunks}};var hr=/[/\\:*?"<>|\x00-\x1F]/g,fr=["CON","PRN","AUX","NUL","COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","LPT1","LPT2","LPT3","LPT4","LPT5","LPT6","LPT7","LPT8","LPT9"];function H(n){let e=n.replace(hr,"_");e=e.replace(/[. ]+$/,""),(!e||e==="."||e==="..")&&(e="unnamed");let t=e.includes(".")?e.substring(0,e.lastIndexOf(".")):e;fr.includes(t.toUpperCase())&&(e=`_${e}`);let r=new TextEncoder;if(r.encode(e).length>255){let s=e.lastIndexOf("."),o=s>0?e.substring(s):"",i=s>0?e.substring(0,s):e,l=255-r.encode(o).length;for(;r.encode(i).length>l&&i.length>0;)i=i.slice(0,-1);e=i+o}return e}var L=class extends Error{constructor(){super("Upload cancelled"),this.name="CancelledError"}};function M(n){return n instanceof L||n instanceof Error&&n.name==="CancelledError"||n instanceof Error&&n.name==="CanceledError"||n instanceof Error&&n.name==="AbortError"}function Fr(n){return M(n)||n instanceof Error&&n.name==="NoAuthError"}function Er(n){return new Promise(e=>setTimeout(e,n))}function wr(n){return n instanceof Blob?n.size:n.byteLength}var ae=class{#e;#s;#t;#o;#r;#n;#i;#c;#l;#u;#p;#a;#k;#g=null;#I=0;#P=!1;#C=[];#h=new Set;#b=!1;#E=!1;#R=!1;#m=[];#y=!1;#T=!1;#d=new ke;#v=0;#f=new Map;#w=new Map;#L=[];#B=!1;#D=null;#M;#x="keep_both";#_=new Map;#N=null;#S=!1;#A=null;#O=!1;constructor(e){this.#e=e.httpClient,this.#s=new Te(e.httpClient),this.#t=new Re,this.#o=e.historyStore??null,this.#r=e.settingsStore??null,this.#n=e.analytics??null,this.#i=e.logger??dt,this.#c=e.onChange??null,this.#l=e.onClear??null,this.#u=e.onSummary??null,this.#p=e.onConcurrencyAdjusted??null,this.#k=e.deltaIntervalMs??333;let t=e.maxConcurrency??4;if(e.adaptiveConcurrency!==!1){let r=e.adaptiveConcurrencyConfig;this.#A=new oe({initialConcurrency:r?.initialConcurrency??Math.min(4,t),minConcurrency:r?.minConcurrency??1,maxConcurrency:r?.maxConcurrency??t,errorThreshold:r?.errorThreshold,cooldownSeconds:r?.cooldownSeconds??10,plateauThreshold:r?.plateauThreshold,onChange:s=>{let o=this.#a;if(this.setMaxConcurrency(s),o===s)return;let i=this.#O?"reset":s>o?"probe_increase":"error_decrease",a=Math.round(this.#A.speedBps*8/1e6*100)/100,l=Math.round(this.#A.latencyMsPerMB*100)/100;this.#i.info(`Adaptive concurrency: ${o} \u2192 ${s} (${i}), measuredAt=${o}, speed=${a}Mbps, latency=${l}ms/MB`),this.#p?.({previousConcurrency:o,newConcurrency:s,reason:i,speedMbps:a,latencyMsPerMB:l})},now:r?.now}),this.#a=this.#A.concurrency}else this.#a=t;this.#o&&(this.#C=this.#o.load()),this.#r&&(this.#D=this.#r.getBandwidthLimitBps(),this.#x=this.#r.getConflictResolution()),this.#M=new j(this.#D),(this.#c||this.#u)&&(this.#g=setInterval(()=>{this.#ce()},this.#k)),this.#n&&(this.#N=setInterval(()=>{this.#de()},6e4))}startUpload(e){let t=e.assetId||crypto.randomUUID(),r=!!e.assetId,s;if(r){let i=this.#t.getUploadAsset(t);if(!i)throw new Error(`Cannot retry: asset ${t} not found`);s=i.chunkSize}else{if(e.chunkSize===void 0||e.chunkSize===null)throw new Error("chunkSize is required for new uploads");s=e.chunkSize}let o=new AbortController;if(r){if(this.#t.getUploadAsset(t).status==="cancelled")return t;e.resetRetryCount&&this.#t.resetAssetForRetrying(t);let a=this.#t.getUploadAsset(t);a.abortController=o,a.fileReader=e.fileReader,e.shareContext&&(a.shareContext=e.shareContext)}else this.#t.addUploadAsset({assetId:t,fileReader:e.fileReader,abortController:o,parentId:e.directoryId,projectId:e.projectId,groupId:e.groupId,chunkSize:s,shareContext:e.shareContext});return this.#m.push(t),this.#U(),this.#F(),t}startGroupUpload(e){this.#t.clearTerminalState();let t=this.#t.addUploadGroup({type:e.type,name:e.name,assetIds:[],fileCount:e.fileCount,folderCount:e.folderCount,topLevelFileCount:e.topLevelFileCount,topLevelFolderCount:e.topLevelFolderCount,isCreatingFolders:!1,isPaused:!1,createdAt:new Date().toISOString(),rootDirectoryId:e.rootDirectoryId,projectId:e.projectId,retryCount:0,conflictResolution:e.conflictResolutionOverride??this.#x});return this.#_.set(t,Date.now()),this.#n?.("upload:started",{file_count:e.fileCount,total_bytes:e.totalBytes??0,has_folders:e.folderCount>0,project_id:e.projectId}),this.#t.dirtyHistoryGroupIds.add(t),this.#$(),this.#F(),t}pauseUpload(e){let t=this.#t.getUploadAsset(e);this.#t.pauseUpload(e),this.#m=this.#m.filter(r=>r!==e),this.#d.pauseAsset(e),!this.#S&&t&&this.#n&&this.#n("upload:file_paused",{file_name:t.fileName,file_size:t.totalBytesToUpload,bytes_uploaded:t.bytesUploaded,project_id:t.projectId??""}),this.#F()}unpauseUpload(e){this.#t.unpauseUpload(e),this.#F()}cancelUpload(e){let t=this.#t.getUploadAsset(e);if(!t||t.status==="success"||t.status==="failed"||t.status==="cancelled")return;let r=t.fileName,s=t.totalBytesToUpload,o=t.bytesUploaded,i=t.projectId,a=t.chunkedState?.assetId;(t.status==="queued"||t.status==="in-progress")&&t.abortController.abort(),this.#m=this.#m.filter(l=>l!==e),this.#d.removeAsset(e),this.#f.delete(e),this.#w.delete(e),this.#t.markUploadCancelled(e),this.#t.clearChunkedState(e),t.fileReader.close?.(),!this.#S&&this.#n&&this.#n("upload:file_cancelled",{file_name:r,file_size:s,bytes_uploaded:o,project_id:i??""}),this.#F(),this.#z(),this.#U(),this.#Q(),a&&(this.#L.push(a),this.#X())}cancelAllUploads(){let e=this.#V();this.#S=!0;try{let r=Object.values(this.#t.uploadAssets).filter(s=>s.status==="queued"||s.status==="in-progress"||s.status==="paused");for(let s of r)this.cancelUpload(s.assetId)}finally{this.#S=!1}this.#n?.("upload:all_cancelled",e)}retryUpload(e){let t=this.#t.getUploadAsset(e);t&&t.status==="failed"&&this.startUpload({fileReader:t.fileReader,directoryId:t.parentId??"",projectId:t.projectId,groupId:t.groupId,assetId:e,resumeChunked:t.chunkedState,resetRetryCount:!0,shareContext:t.shareContext})}resumeUpload(e){let t=this.#t.getUploadAsset(e);if(!t||t.status!=="paused")return;!this.#S&&this.#n&&this.#n("upload:file_resumed",{file_name:t.fileName,file_size:t.totalBytesToUpload,bytes_uploaded:t.bytesUploaded,project_id:t.projectId??""});let r=new AbortController;t.abortController=r,this.#t.unpauseUpload(e),this.#d.hasAsset(e)?(this.#d.unpauseAsset(e),this.#F(),this.#d.isAssetComplete(e)?this.#J(e).catch(s=>{this.#G(e,s)}):this.#z()):this.startUpload({fileReader:t.fileReader,directoryId:t.parentId??"",projectId:t.projectId,groupId:t.groupId,assetId:e,resumeChunked:t.chunkedState,shareContext:t.shareContext})}pauseUploadGroup(e){let t=this.#t.uploadGroups[e];if(!t)return;let r=this.#S;this.#S=!0,this.#t.pauseUploadGroup(e);for(let s of t.assetIds)this.#m=this.#m.filter(o=>o!==s),this.#d.pauseAsset(s);this.#S=r,this.#S||this.#te(e,t,"upload:group_paused"),this.#F()}unpauseUploadGroup(e){this.#t.unpauseUploadGroup(e),this.#F()}cancelUploadGroup(e){let t=this.#t.uploadGroups[e];if(!t)return;let{totalBytes:r,bytesUploaded:s,filesRemaining:o}=this.#ee(t),i=this.#S;this.#S=!0;for(let a of t.assetIds)this.cancelUpload(a);t.assetIds.length===0&&(this.#t.finalizeEmptyGroup({groupId:e,status:"cancelled"}),this.#$(),this.#F()),this.#S=i,this.#S||this.#n?.("upload:group_cancelled",{file_count:t.assetIds.length,files_remaining:o,total_bytes:r,bytes_uploaded:s,project_id:t.projectId}),this.#_.delete(e)}resumeUploadGroup(e){let t=this.#t.uploadGroups[e];if(!t)return;this.#S||this.#te(e,t,"upload:group_resumed");let r=this.#S;this.#S=!0,this.#t.unpauseUploadGroup(e);for(let s of t.assetIds){let o=this.#t.getUploadAsset(s);o&&o.status==="paused"&&this.resumeUpload(s)}this.#S=r}retryUploadGroup(e){let t=this.#t.uploadGroups[e];if(t)for(let r of t.assetIds){let s=this.#t.getUploadAsset(r);s&&s.status==="failed"&&this.retryUpload(r)}}setGroupCreatingFolders(e,t){this.#t.updateUploadGroup(e,{isCreatingFolders:t}),this.#F()}markEmptyGroupFailed(e,t){let r=this.#t.uploadGroups[e];r&&(r.assetIds.length>0||r.finalizedStatus||(this.#i.error("Empty group upload failed",{groupId:e,groupName:r.name,errorMessage:t}),this.#t.finalizeEmptyGroup({groupId:e,status:"all-failed",errorMessage:t}),this.#$(),this.#_.delete(e),this.#F()))}markEmptyGroupCompleted(e){this.#t.finalizeEmptyGroup({groupId:e,status:"success"}),this.#$(),this.#_.delete(e),this.#F()}addAssetToGroup(e,t){this.#t.addAssetToGroup(e,t)}pauseAllUploads(){let e=this.#V();this.#S=!0;try{for(let t of Object.values(this.#t.uploadAssets))t.groupId||this.pauseUpload(t.assetId);for(let t of Object.values(this.#t.uploadGroups))t.isCreatingFolders||this.pauseUploadGroup(t.id)}finally{this.#S=!1}this.#n?.("upload:all_paused",e),this.#F()}resumeAllUploads(){let e=this.#V();this.#S=!0;try{for(let t of Object.values(this.#t.uploadAssets))!t.groupId&&t.status==="paused"&&this.resumeUpload(t.assetId);for(let t of Object.values(this.#t.uploadGroups))t.isPaused&&this.resumeUploadGroup(t.id)}finally{this.#S=!1}this.#n?.("upload:all_resumed",e),this.#F()}clearAllUploads(){this.#m=[],this.#d.clear(),this.#f.clear(),this.#w.clear(),this.#t.clearAllUploads(),this.#t.uploadGroups={},this.#A&&(this.#O=!0,this.#A.reset(),this.#O=!1),this.#l?.({all:!0}),this.#u?.(this.#H())}clearHistory(){this.#C=[],this.#o?.clear(),this.#b=!0,this.#h.clear(),this.#R=!0,this.#F()}removeHistoryItem(e){this.#C=this.#C.filter(t=>t.groupId!==e),this.#o?.remove(e),this.#h.add(e),this.#R=!0,this.#F()}removeGroup(e){this.#t.removeUploadGroup(e),this.#C=this.#C.filter(t=>t.groupId!==e),this.#o?.remove(e),this.#h.add(e),this.#R=!0,this.#l?.({groupId:e}),this.#u?.(this.#H()),this.#F()}getHttpClient(){return this.#e}setBandwidthLimit(e){let t=e!==this.#D;this.#D=e,this.#M.setLimit(e),this.#r?.setBandwidthLimitBps(e),t&&this.#A&&(this.#O=!0,this.#A.reset(),this.#O=!1),this.#R=!0,this.#F()}getBandwidthLimit(){return this.#D}setConflictResolution(e){this.#x=e,this.#r?.setConflictResolution(e),this.#R=!0,this.#F()}getConflictResolution(){return this.#x}getGroupConflictResolution(e){return this.#t.getUploadGroup(e)?.conflictResolution??this.#x}setMaxConcurrency(e){this.#a=e,this.#z()}getSnapshot(){return this.#t.updateUploadStats(),{...this.#t.getSerializableSnapshot(),uploadHistory:[...this.#C??[]],uploadSummary:this.#H(),bandwidthLimitBps:this.#D,conflictResolution:this.#x}}getUploadAsset(e){return this.#t.getSerializableAsset(e)}getUploadSummary(){return this.#H()}getGroupAssets(e){return this.#t.getGroupAssets(e)}getUploadGroupStatus(e){return this.#t.getUploadGroupStatus(e)}getUploadGroupProgress(e){return this.#t.getUploadGroupProgress(e)}hasGroupsCreatingFolders(){return this.#t.hasGroupsCreatingFolders()}areAllUploadsPaused(){return this.#t.areAllUploadsPaused()}hasPausedUploads(){return this.#t.hasPausedUploads()}hasActiveUploads(){return lt(this.#t.getSerializableSnapshot().uploadAssets)}getServerAssetIdsToCancel(){return at(this.#t.getSerializableSnapshot().uploadAssets)}async cancelActiveServerUploads(){let e=this.getServerAssetIdsToCancel();if(e.length!==0)try{await this.#e.post("/assets/cancel-uploads",{asset_ids:e})}catch{await this.#e.post("/assets/cancel-uploads",{asset_ids:e})}}destroy(){this.#E=!0,this.#g&&(clearInterval(this.#g),this.#g=null),this.#N&&(clearInterval(this.#N),this.#N=null),this.#m=[],this.#d.clear();for(let e of Object.values(this.#t.uploadAssets))e.abortController.abort(),e.fileReader.close?.()}#U(){this.#T||(this.#T=!0,queueMicrotask(()=>{this.#T=!1,this.#W().catch(e=>{this.#i.error("Initiation pipeline error",{queueLength:this.#m.length},e)})}))}async#W(){if(!this.#y){this.#y=!0;try{await this.#K()}finally{this.#y=!1}}}async#K(){for(;this.#m.length>0&&!(this.#f.size>5);){let e=Math.min(this.#m.length,20-this.#f.size);if(e<=0)break;let t=[],r=[];for(let s=0;s<e&&this.#m.length>0;s++){let o=this.#m[0],i=this.#t.getUploadAsset(o);if(!i||i.status==="cancelled"){this.#m.shift(),s--;continue}if(this.#m.shift(),r.push(o),i.chunkedState)try{this.#Y(o,i),this.#z()}catch(a){M(a)||this.#G(o,a)}else t.push(o)}if(t.length>0){let s=new Map;for(let o of t){let a=this.#t.getUploadAsset(o)?.shareContext?.shareId??"",l=s.get(a);l||(l=[],s.set(a,l)),l.push(o)}for(let o of s.values())try{await this.#j(o)}catch(i){for(let a of o)this.#G(a,i instanceof Error?i:new Error(String(i)))}this.#z()}}}#Y(e,t){let r=t.chunkedState,s={serverAssetId:r.assetId,chunkIds:r.chunkIds,chunkSize:r.chunkSize,totalChunks:r.totalChunks,sizeBytes:r.sizeBytes},o=r.completedChunkIndices;this.#f.set(e,s);let i=new Array(s.totalChunks).fill(0);if(o.length>0){for(let l of o){let c=l*s.chunkSize,u=Math.min(c+s.chunkSize,t.totalBytesToUpload);i[l]=u-c}let a=i.reduce((l,c)=>l+c,0);this.#t.updateUploadProgress(e,a)}if(this.#w.set(e,i),s.totalChunks===0||o.length>=s.totalChunks){this.#J(e).catch(a=>{this.#G(e,a)});return}this.#d.registerAsset({assetId:e,totalChunks:s.totalChunks,completedChunkIndices:o})}async#j(e){let t=[],r=[];for(let a of e){let l=this.#t.getUploadAsset(a);if(!l||l.status==="cancelled")continue;let c=H(l.fileName),u=l.groupId?this.#t.getUploadGroup(l.groupId)?.conflictResolution??this.#x:this.#x,d=(()=>{switch(u){case"keep_both":return{auto_rename:"parenthesized"};case"replace":return{conflict_resolution:"replace"};case"skip":return{conflict_resolution:"skip"}}})();t.push({directory_id:l.parentId,id:a,name:c,size_bytes:l.totalBytesToUpload,...d}),r.push(a)}if(t.length===0)return;let s=this.#t.getUploadAsset(r[0]),o=s?.shareContext?O(s.shareContext):void 0,i=await this.#e.post("/assets/chunked/initiate",t,o);for(let a=0;a<r.length;a++){let l=r[a],c=i[a];if(!c||c.error){this.#G(l,new Error(c?.error??"Unknown batch initiation error"));continue}if(c.skipped){let C=this.#t.getUploadAsset(l);C&&(this.#t.adjustSpeedBaselineForSkippedBytes(C.totalBytesToUpload),this.#t.markUploadSuccess(l),this.#t.dirtyHistoryGroupIds.add(C.groupId??""),this.#$(),C.fileReader.close?.());continue}let u=c.result,d=this.#t.getUploadAsset(l);if(!d||d.status==="cancelled"||d.status==="paused"){(!d||d.status==="cancelled")&&(this.#L.push(u.asset_id),this.#X());continue}let m=Math.ceil(d.totalBytesToUpload/u.chunk_size),f=Array.from({length:m},()=>crypto.randomUUID());this.#s.seedToken(u.asset_id,u.token,u.token_expires_at);let p={serverAssetId:u.asset_id,chunkIds:f,chunkSize:u.chunk_size,totalChunks:m,sizeBytes:d.totalBytesToUpload};this.#t.setChunkedState(l,{assetId:p.serverAssetId,chunkIds:p.chunkIds,completedChunkIndices:[],chunkSize:p.chunkSize,totalChunks:p.totalChunks,sizeBytes:p.sizeBytes}),this.#f.set(l,p);let y=new Array(p.totalChunks).fill(0);if(this.#w.set(l,y),p.totalChunks===0){this.#J(l).catch(C=>{this.#G(l,C)});continue}this.#d.registerAsset({assetId:l,totalChunks:p.totalChunks,completedChunkIndices:[]})}}#z(){if(!this.#E)for(;this.#v<this.#a;){let e=this.#d.claimNextChunk();if(!e)break;this.#v++;let{assetId:t,chunkIndex:r}=e,s=this.#A?.generation;this.#re(t,r,s).then(o=>{this.#v--,this.#oe(t,r,o),this.#z()}).catch(o=>{if(this.#v--,M(o)){this.#z();return}this.#ie(t,r,o),this.#z()})}}async#re(e,t,r){let s;for(let o=0;o<3;o++)try{let i=this.#w.get(e);return i&&(i[t]=0,this.#q(e)),await this.#se(e,t,r)}catch(i){if(M(i))throw i;if(s=i instanceof Error?i:new Error(String(i)),this.#A?.recordError(),this.#ae(e,t,s,o),o===2)throw s;let a=this.#w.get(e);a&&(a[t]=0,this.#q(e));let l=1e3*Math.pow(2,o);await Er(l)}throw s||new Error("Unknown error during chunk upload")}async#se(e,t,r){let s=this.#t.getUploadAsset(e);if(!s)throw new L;if(s.abortController.signal.aborted)throw new L;let o=this.#f.get(e);if(!o)throw new Error(`No chunk metadata for asset ${e}`);let i=t*o.chunkSize,a=Math.min(i+o.chunkSize,s.totalBytesToUpload),l=await s.fileReader.readChunk(i,a),c=wr(l);if(s.abortController.signal.aborted)throw new L;let u=o.chunkIds[t],d=await this.#s.getToken(o.serverAssetId,s.shareContext),m=`/uploads/chunks/${u}`,f=Date.now(),p=await this.#e.putWithToken(m,l,d,{signal:s.abortController.signal,onProgress:k=>{let E=this.#w.get(e);E&&(E[t]=k,this.#q(e))},contentType:"application/octet-stream",limiter:this.#M}),y=Date.now(),C=p.uploadCompletedAtMs??y,S=C-f;if(!p.status||p.status<200||p.status>=300)throw this.#i.error("Chunk upload returned unexpected status",{chunkIndex:t,chunkId:u,assetId:e,serverAssetId:o.serverAssetId,chunkSizeBytes:c,durationMs:S,httpStatus:p.status,statusText:p.statusText,responseBody:p.data,responseHeaders:p.headers}),new Error(`Chunk ${t} upload failed: unexpected status ${p.status}`);let we=this.#w.get(e);return we&&(we[t]=c,this.#q(e)),{durationMs:S,startedAtMs:f,completedAtMs:C,adaptiveGeneration:r}}#q(e){let t=this.#w.get(e);if(!t)return;let r=t.reduce((s,o)=>s+o,0);this.#t.updateUploadProgress(e,r)}#oe(e,t,r){if(this.#A){let o=this.#f.get(e);if(o){let i=t*o.chunkSize,l=Math.min(i+o.chunkSize,o.sizeBytes)-i;this.#A.recordSuccess(l,r.durationMs,{generation:r.adaptiveGeneration,startedAtMs:r.startedAtMs,completedAtMs:r.completedAtMs})}}this.#t.addCompletedChunkIndex(e,t),this.#d.markChunkCompleted(e,t)&&this.#J(e).catch(o=>{this.#G(e,o)})}#ie(e,t,r){this.#G(e,r)}#ae(e,t,r,s){if(!this.#n)return;let o=this.#t.getUploadAsset(e);if(!o)return;let i=this.#f.get(e);if(!i)return;let a=t*i.chunkSize,c=Math.min(a+i.chunkSize,i.sizeBytes)-a,u=r,d=typeof u.code=="string"?u.code:null,m=u.response?.status,f=typeof m=="number"?m:null,p=r.cause?r.cause instanceof Error?r.cause.message:String(r.cause):null,y=ht(r);this.#n("upload:chunk_error",{file_name:o.fileName,file_size:o.totalBytesToUpload,chunk_index:t,chunk_size:c,chunks_total:i.totalChunks,attempt:s+1,max_attempts:3,is_final_attempt:s===2,error_type:r.name,error_message:r.message,error_code:d,http_status:f,error_stack:r.stack??null,error_cause:p,project_id:o.projectId??"",had_response:y?.hadResponse??null,reused_socket:y?.reusedSocket??null,remote_address:y?.remoteAddress??null,remote_family:y?.remoteFamily??null,tls_protocol:y?.tlsProtocol??null,tls_cipher:y?.tlsCipher??null,peer_cert_issuer:y?.peerCertIssuer??null,peer_cert_subject:y?.peerCertSubject??null,tls_authorized:y?.tlsAuthorized??null})}#le(e,t,r,s){if(!this.#n||M(t))return;let o=t instanceof Error?t.message:"Unknown error",i=t,a=t instanceof Error&&t.cause?t.cause instanceof Error?t.cause.message:String(t.cause):null,l=typeof i.code=="string"?i.code:null,c=i.response?.status,u=typeof c=="number"?c:null,d=this.#f.get(e.assetId);this.#n("upload:file_error",{file_name:e.fileName,file_size:e.totalBytesToUpload,bytes_uploaded:e.bytesUploaded,chunks_completed:e.chunkedState?.completedChunkIndices.length??0,chunks_total:d?.totalChunks??0,attempt:r+1,max_attempts:4,is_final_attempt:s,error_type:t instanceof Error?t.name:"Unknown",error_message:o,error_code:l,http_status:u,error_stack:t instanceof Error?t.stack??null:null,error_cause:a,project_id:e.projectId??""})}async#J(e){let t=this.#t.getUploadAsset(e);if(!t)return;let r=this.#f.get(e);if(!r)return;if(t.abortController.signal.aborted)throw new L;let s=crypto.randomUUID(),o=JSON.stringify(r.chunkIds),i=new TextEncoder().encode(o),a=await this.#s.getToken(r.serverAssetId,t.shareContext),l=`/uploads/manifests/${s}`;try{await this.#e.putWithToken(l,i,a,{signal:t.abortController.signal,contentType:"application/json"})}catch(c){throw M(c)||this.#i.error("Manifest upload failed",{assetId:e,serverAssetId:r.serverAssetId,manifestId:s},c),c}if(t.abortController.signal.aborted)throw new L;try{let c=t.shareContext?O(t.shareContext):void 0;await this.#e.post(`/assets/${r.serverAssetId}/revisions/commit`,{manifest_id:s,size_bytes:r.sizeBytes,is_initial_upload:!0,client_performed_at:new Date().toISOString()},c)}catch(c){throw this.#i.error("Commit revision failed",{assetId:e,serverAssetId:r.serverAssetId,manifestId:s,sizeBytes:r.sizeBytes},c),c}this.#t.markUploadSuccess(e),this.#t.clearChunkedState(e),this.#$(),this.#F(),this.#f.delete(e),this.#w.delete(e),this.#d.removeAsset(e),await t.fileReader.close?.(),this.#ne(e),this.#U(),this.#Q()}#G(e,t){let r=this.#t.getUploadAsset(e);if(!r||M(t)||r.status==="paused"||r.status==="cancelled")return;let s=r.retryCount,o=s>=3||Fr(t);if(this.#le(r,t,s,o),o){let i=t instanceof Error?t.message:"Unknown error";this.#i.error("Asset upload permanently failed",{assetId:e,fileName:r.fileName,totalRetries:s,bytesUploaded:r.bytesUploaded,totalBytes:r.totalBytesToUpload,chunksCompleted:r.chunkedState?.completedChunkIndices.length??0},t),r.abortController.abort(),this.#t.markUploadFailed(e,i),this.#d.removeAsset(e),this.#f.delete(e),this.#w.delete(e),this.#$(),this.#F(),this.#ne(e),this.#U(),this.#Q()}else{this.#i.warn("Asset upload failed, scheduling retry",{assetId:e,fileName:r.fileName,retryAttempt:s+1,maxRetries:3},t);let i=r.chunkedState;r.abortController.abort(),this.#d.removeAsset(e),this.#f.delete(e),this.#w.delete(e),this.#t.resetAssetForRetryQueue(e),this.#F(),this.#U();let a=2e3*Math.pow(2,s);setTimeout(()=>{if(this.#E)return;let l=this.#t.getUploadAsset(e);!l||l.status!=="queued"||this.startUpload({fileReader:l.fileReader,directoryId:l.parentId??"",projectId:l.projectId,groupId:l.groupId,assetId:e,resumeChunked:i,shareContext:l.shareContext})},a)}}#Q(){this.#A&&(this.hasActiveUploads()||(this.#O=!0,this.#A.reset(),this.#O=!1))}#X(){this.#B||(this.#B=!0,queueMicrotask(()=>{this.#B=!1;let e=this.#L.splice(0);e.length!==0&&this.#e.post("/assets/cancel-uploads",{asset_ids:e}).catch(t=>{this.#i.error("Failed to batch abort uploads",{assetIds:e},t)})}))}#H(){return re(this.#t.getSerializableSnapshot().uploadAssets)}#F(){this.#P||(this.#P=!0,queueMicrotask(()=>{this.#P=!1,this.#ue()}))}#ce(){this.#Z(!0)}#ue(){this.#Z(!1)}#Z(e){if(this.#E||!this.#c&&!this.#u)return;e?this.#t.updateUploadStats():(this.#I++,this.#I%3===0&&this.#t.updateUploadStats());let t=this.#t.getDirtyDelta();if(!this.#R&&Object.keys(t.assets).length===0&&Object.keys(t.groups).length===0&&this.#t.dirtyHistoryGroupIds.size===0)return;this.#R=!1,this.#t.dirtyHistoryGroupIds.size>0&&this.#$();let s=this.#t.dirtyHistoryGroupIds.size>0?this.#pe():void 0,o=this.#b?!0:void 0,i=this.#h.size>0?[...this.#h]:void 0;this.#b=!1,this.#h.clear();let a=this.#H(),l={assets:t.assets,groups:t.groups,uploadStats:{...this.#t.uploadStats},uploadSpeedState:this.#t.uploadSpeedState,historyItems:s,removedHistoryGroupIds:i,historyCleared:o,uploadSummary:a,bandwidthLimitBps:this.#D,conflictResolution:this.#x};this.#t.clearDirtyFlags(),this.#c?.(l),this.#u?.(a)}#ee(e){let t=0,r=0,s=0;for(let o of e.assetIds){let i=this.#t.getUploadAsset(o);i&&(t+=i.totalBytesToUpload,r+=i.bytesUploaded,i.status!=="success"&&i.status!=="failed"&&i.status!=="cancelled"&&s++)}return{totalBytes:t,bytesUploaded:r,filesRemaining:s}}#V(){let e=0,t=0,r=0,s=0;for(let o of Object.values(this.#t.uploadGroups)){e++;for(let i of o.assetIds){let a=this.#t.getUploadAsset(i);a&&(a.status==="success"||a.status==="failed"||a.status==="cancelled"||(t++,r+=a.totalBytesToUpload,s+=a.bytesUploaded))}}return{group_count:e,file_count:t,total_bytes:r,bytes_uploaded:s}}#de(){if(!(!this.#n||this.#E))for(let e of Object.values(this.#t.uploadGroups)){let t=!1,r=0,s=0,o=0,i=0,a=0,l=0,c=0,u=0,d=0,m=0;for(let y of e.assetIds){let C=this.#t.getUploadAsset(y);if(!C)continue;let S=C.totalBytesToUpload;switch(r+=S,s+=C.bytesUploaded,C.status){case"success":o++,i+=S;break;case"failed":a++,l+=S;break;case"cancelled":c++,u+=S;break;case"in-progress":d++,t=!0;break;case"queued":m++,t=!0;break;case"paused":t=!0;break}}if(!t)continue;let f=this.#_.get(e.id),p=f?Date.now()-f:0;this.#n("upload:group_progress",{group_id:e.id,file_count:e.assetIds.length,total_bytes:r,bytes_uploaded:s,duration_ms:p,project_id:e.projectId,succeeded_count:o,succeeded_bytes:i,failed_count:a,failed_bytes:l,cancelled_count:c,cancelled_bytes:u,in_progress_count:d,queued_count:m,progress:r>0?s/r:0,concurrency:this.#a,upload_speed_mbps:this.#t.uploadStats.uploadSpeedMbps})}}#te(e,t,r){if(!this.#n)return;let{totalBytes:s,bytesUploaded:o}=this.#ee(t);this.#n(r,{file_count:t.fileCount,total_bytes:s,bytes_uploaded:o,project_id:t.projectId})}#ne(e){if(!this.#n)return;let t=this.#t.getUploadAsset(e);if(!t?.groupId)return;let r=this.#t.uploadGroups[t.groupId];if(!r)return;let s=!0,o=0,i=0,a=0,l=0,c=0,u=0,d=0;for(let p of r.assetIds){let y=this.#t.getUploadAsset(p);if(!y)continue;let C=y.totalBytesToUpload;if(d+=C,y.status==="success")o++,i+=C;else if(y.status==="failed")a++,l+=C;else if(y.status==="cancelled")c++,u+=C;else{s=!1;break}}if(!s)return;let m=this.#_.get(r.id),f=m?Date.now()-m:0;this.#n("upload:group_completed",{file_count:r.assetIds.length,total_bytes:d,duration_ms:f,project_id:r.projectId,succeeded_count:o,succeeded_bytes:i,failed_count:a,failed_bytes:l,cancelled_count:c,cancelled_bytes:u}),this.#_.delete(r.id)}#pe(){let e={};for(let t of this.#t.dirtyHistoryGroupIds){let r=this.#t.buildHistoryItem(t);r&&(e[t]=r)}return e}#$(){if(!this.#o)return;let e={};for(let t of this.#t.dirtyHistoryGroupIds){let r=this.#t.buildHistoryItem(t);if(r){e[t]=r;let s=this.#C.findIndex(o=>o.groupId===t);s>=0?this.#C[s]=r:this.#C.unshift(r)}}Object.keys(e).length>0&&this.#o.merge(e)}};var Ir={keep_both:"Keep Both",replace:"Replace",skip:"Skip"};var _a=new Set(["success","all-failed","some-failed","cancelled"]),Oa=new Set(["all-failed","some-failed"]),Ba=new Set(["queued","in-progress"]),Ma=new Set(["queued","creating-folders","in-progress"]),Na=new Set(["queued","in-progress"]),za=new Set(["queued","in-progress","paused"]);var ce=class{#e=65536;#s=0;async*createIterator(e,t,r){let s=0,o=Math.max(65536,Math.min(e.byteLength,this.#e)),i=this.#s;for(;s<e.byteLength;){if(r?.aborted)return;let a=t?t.getLimit():null,l=a!==null&&a>0;if(l){let p=Math.round(a*50/1e3);o=Math.max(65536,Math.min(e.byteLength,p))}let c=Math.min(s+o,e.byteLength),u=e.subarray(s,c),d=u.byteLength;if(l&&(await t.acquire(d),r?.aborted))return;let m=performance.now();yield u;let f=performance.now()-m;if(s=c,!l){if(f>=.5){let p=d/f*1e3;i=i===0?p:i*(1-.3)+p*.3}else i===0&&(o=Math.min(e.byteLength,o*2));if(i>0){let p=Math.round(i*50/1e3);o=Math.max(65536,Math.min(e.byteLength,p))}}this.#e=o,this.#s=i}}};var x=class{#e;#s;#t;#o;#r=new ce;#n=new Set;constructor(e){this.#e=Xt.create({baseURL:e.apiUrl}),this.#s=Xt.create({baseURL:e.edgeWorkerUrl}),this.#t=e.apiKey,this.#o=e.sessionId}get skippedAssetIds(){return this.#n}async post(e,t,r){let s=await this.#e.post(e,t,{headers:{Authorization:`Bearer ${this.#t}`,"X-Aspect-Session-Id":this.#o,"Content-Type":"application/json",...r}});return this.#c(e,t,s.data),s.data}async get(e,t){return(await this.#e.get(e,{headers:{Authorization:`Bearer ${this.#t}`,"X-Aspect-Session-Id":this.#o,...t}})).data}async delete(e,t){await this.#e.delete(e,{headers:{Authorization:`Bearer ${this.#t}`,"X-Aspect-Session-Id":this.#o,...t}})}async putWithToken(e,t,r,s){let o=await this.#i(t),i=this.#r.createIterator(o,s.limiter??null,s.signal),a=Pr.from(i,{highWaterMark:1}),l;try{l=await this.#s.put(e,a,{timeout:0,signal:s.signal,headers:{"Content-Type":s.contentType??"","Content-Length":o.byteLength.toString(),Authorization:`Bearer ${r}`},transformRequest:[c=>c],maxRedirects:0,onUploadProgress:c=>s.onProgress?.(c.loaded)})}catch(c){throw mt(c,pt(c)),c}return{status:l.status,statusText:l.statusText,headers:Object.fromEntries(Object.entries(l.headers)),data:l.data,raw:l}}async#i(e){if(e instanceof Uint8Array)return e;let t=await e.arrayBuffer();return new Uint8Array(t)}#c(e,t,r){if(e!=="/assets/chunked/initiate"||!Array.isArray(t)||!Array.isArray(r))return;let s=t;r.forEach((i,a)=>{let l=s[a];i.skipped===!0&&typeof l?.id=="string"&&this.#n.add(l.id)})}};import de from"node:path";import D from"node:path";function b(n){let e=n.replace(/\\/g,"/");if(e.split("/").some(o=>o===".."))throw new Error(`Remote path cannot contain parent directory segments: ${n}`);let s=D.posix.normalize(e).replace(/^\/+/,"");if(s===""||s===".")throw new Error(`Remote path must resolve to a file path: ${n}`);return s}function Ue(n){let e=new Map;for(let o of n){let i=b(o.targetPath??o.path);e.set(i,(e.get(i)??0)+1)}let t=new Set,r=[],s=[];for(let o of n){let i=b(o.path),a=b(o.targetPath??o.path),l=ue(a),c=yt(l,t),u=(e.get(a)??0)>1,d=c!==i;t.add(c),r.push({...o,targetPath:c,requiresIdentityDownload:o.requiresIdentityDownload===!0||u}),(d||u)&&s.push({sourcePath:o.path,targetPath:c,reason:u||c!==l?"duplicate":"sanitized"})}return{files:r,changes:s}}function F(n){return b(n.targetPath??n.path)}function Le(n,e){let t=F(n);return{relativePath:t,absolutePath:D.join(e,t),fileName:D.posix.basename(t),size:n.size}}function ue(n){return n.split("/").map(t=>H(t)).join("/")}function yt(n,e){if(!e.has(n))return n;let t=D.posix.dirname(n),r=D.posix.basename(n),s=D.posix.extname(r),o=s.length>0?r.slice(0,-s.length):r,i=2;for(;;){let a=`${o} (${i})${s}`,l=t==="."?a:`${t}/${a}`;if(!e.has(l))return l;i+=1}}function St(n,e){if(!e.has(n))return n;let t=D.posix.dirname(n),r=D.posix.basename(n),s=2;for(;;){let o=`${r} ${s}`,i=t==="."?o:`${t}/${o}`;if(!e.has(i))return i;s+=1}}var Zt=500,Rr=8,xe=class{#e;#s;#t=new Map;constructor(e){this.#e=e.rootDirectoryId,this.#s=e.httpClient}async ensureDirectories(e){await this.loadExistingDirectories();let t=this.#o(e);for(let r of t){if(this.#t.has(r))continue;let s=de.posix.dirname(r),o=de.posix.basename(r),i=s==="."?this.#e:this.#t.get(s);if(!i)throw new Error(`Parent directory ID not found for path: ${r}`);let a=await this.#l(i,o);if(a.name!==o)throw new Error(`Server created renamed directory "${a.name}" for planned path "${r}". Refusing to map uploads to an unexpected target path.`);this.#t.set(r,a.id)}return e.map(r=>({file:r,directoryId:this.getDirectoryIdForFile(r.relativePath)}))}async loadExistingDirectories(){let e=await this.#r(this.#e);this.#t.clear(),this.#c(e,"")}getDirectoryIdForFile(e){let t=b(e),r=de.posix.dirname(t);if(r===".")return this.#e;let s=this.#t.get(r);if(!s)throw new Error(`Directory ID not found for path: ${r}`);return s}getExistingDirectoryIdForFile(e){let t=b(e),r=de.posix.dirname(t);return r==="."?this.#e:this.#t.get(r)??null}async checkAssetsExistence(e,t=!0){if(e.length===0)return[];let r=[];for(let s=0;s<e.length;s+=Zt){let o=e.slice(s,s+Zt),i=await this.#s.post("/assets/check-exists-and-uploaded",{items:o,delete_if_not_exist:t});r.push(...i.items)}return r}async listFilesInSubtree(e={}){let t=[{id:this.#e,relativePath:""}],r=[],s=0;for(;s<t.length;){let o=t.slice(s,s+Rr),i=await Promise.all(o.map(a=>this.#n(a)));s+=o.length;for(let a of i)t.push(...a.directories),r.push(...a.files);e.onProgress?.({scannedDirectoryCount:s,queuedDirectoryCount:t.length,fileCount:r.length})}return r}#o(e){let t=new Set;for(let r of e){let s=b(r.relativePath),o=de.posix.dirname(s);if(o===".")continue;let i=o.split("/");for(let a=0;a<i.length;a++)t.add(i.slice(0,a+1).join("/"))}return Array.from(t).sort((r,s)=>r.split("/").length-s.split("/").length)}async#r(e){return this.#s.get(`/directories/${e}/tree`)}async#n(e){let[t,r]=await Promise.all([this.#s.post("/fs/list/directories",{parent_id:e.id}),this.#s.post("/fs/list/assets",{parent_id:e.id})]);return{directories:t.map(s=>({id:s.id,relativePath:this.#i(e.relativePath,s.name)})),files:r.map(s=>({assetId:s.id,relativePath:this.#i(e.relativePath,s.name),sizeBytes:s.size_bytes,isUploaded:s.is_uploaded??!0,uploadStateKnown:typeof s.is_uploaded=="boolean"}))}}#i(e,t){let r=e===""?t:`${e}/${t}`;return b(r)}#c(e,t){let r=t===""?"":t==="."?e.name:`${t}/${e.name}`;r!==""&&this.#t.set(r,e.id);for(let s of e.children){let o=t===""?".":r;this.#c(s,o)}}async#l(e,t){return this.#s.post(`/directories/${e}/directories`,{name:t,auto_rename:"numeric"})}};import{PostHog as Tr}from"posthog-node";var N=null,De="",Ct={};function en(n){N||n.config.analytics.disabled||!n.config.analytics.posthogKey||(De=n.user.id,Ct={service:"data-sync",package_version:n.packageVersion,platform:process.platform,arch:process.arch,node_version:process.version,max_concurrent:n.config.maxConcurrent,batch_mode:n.config.batchSizeBytes!==void 0,batch_size_bytes:n.config.batchSizeBytes??null,source_kind:n.config.source.kind,...n.config.source.kind==="rclone"?{rclone_transfers:n.config.source.rcloneOptions.transfers,rclone_multi_thread_streams:n.config.source.rcloneOptions.multiThreadStreams}:{}},N=new Tr(n.config.analytics.posthogKey,{host:n.config.analytics.posthogHost}),N.identify({distinctId:De,properties:{user_id:n.user.id,email:n.user.email,first_name:n.user.first_name,last_name:n.user.last_name,utm_source_latest:null,utm_medium_latest:null,utm_campaign_latest:null,utm_content_latest:null}}))}function tn(n,e){N&&N.capture({distinctId:De,event:n,properties:{...Ct,...e}})}async function nn(){let n=N;if(kr(),!!n)try{await n.flush()}catch{}}function kr(){N=null,De="",Ct={}}import{spawn as Oe}from"child_process";import*as At from"fs";import*as pe from"path";var w=class extends Error{constructor(t,r){super(t);this.stderr=r;this.name="RcloneError"}stderr};function vr(n){let e=["sync",n.remoteSource,n.localPath];return n.batchFilePath&&e.push("--files-from",n.batchFilePath),e.push("--progress","--stats","1s","--stats-one-line","-v","--transfers",String(n.rcloneOptions.transfers),"--checkers",String(n.rcloneOptions.checkers),"--multi-thread-streams",String(n.rcloneOptions.multiThreadStreams),"--multi-thread-chunk-size",n.rcloneOptions.multiThreadChunkSize,"--multi-thread-cutoff",n.rcloneOptions.multiThreadCutoff,"--fast-list","--buffer-size",n.rcloneOptions.bufferSize),n.rcloneOptions.useMmap&&e.push("--use-mmap"),n.rcloneOptions.extraRcloneArgs?.length&&e.push(...n.rcloneOptions.extraRcloneArgs),e}function Ur(n){let e=["lsjson",n.remoteSource,"--recursive","--fast-list"];return n.extraArgs?.length&&e.push(...n.extraArgs),e}function Lr(n){let e=["backend","query",`${n.remote}:`,n.query];return n.extraArgs?.length&&e.push(...n.extraArgs),e}function xr(n){let e=["copyto",n.remoteFileSource,n.localTargetPath,"--progress","--stats","1s","--stats-one-line","-v","--multi-thread-streams",String(n.rcloneOptions.multiThreadStreams),"--multi-thread-chunk-size",n.rcloneOptions.multiThreadChunkSize,"--multi-thread-cutoff",n.rcloneOptions.multiThreadCutoff,"--buffer-size",n.rcloneOptions.bufferSize];return n.rcloneOptions.useMmap&&e.push("--use-mmap"),n.rcloneOptions.extraRcloneArgs?.length&&e.push(...n.rcloneOptions.extraRcloneArgs),e}function Dr(n){let e=["backend","copyid",`${n.remote}:`,n.fileId,n.localTargetPath];return n.rcloneOptions.extraRcloneArgs?.length&&e.push(...n.rcloneOptions.extraRcloneArgs),e}function W(n,e){let t=e.trim(),r={B:1,k:1024,Ki:1024,KiB:1024,kB:1e3,M:1024*1024,Mi:1024*1024,MiB:1024*1024,MB:1e3*1e3,G:1024*1024*1024,Gi:1024*1024*1024,GiB:1024*1024*1024,GB:1e3*1e3*1e3,T:1024*1024*1024*1024,Ti:1024*1024*1024*1024,TiB:1024*1024*1024*1024,TB:1e3*1e3*1e3*1e3};return n*(r[t]||1)}function rn(n){let e=0,t=n.match(/(\d+)h/),r=n.match(/(\d+)m/),s=n.match(/(\d+)s/);return t&&(e+=parseInt(t[1],10)*3600),r&&(e+=parseInt(r[1],10)*60),s&&(e+=parseInt(s[1],10)),e}function _r(n){let e=n.trim(),t=/^([\d.]+)\s*([A-Za-z]+)\s*\/\s*([\d.]+)\s*([A-Za-z]+),\s*([\d.]+)%?,\s*([\d.]+)\s*([A-Za-z]+)\/s,\s*ETA\s+(.+)$/,r=e.match(t);if(r){let l=r[8].trim(),c={bytesTransferred:W(parseFloat(r[1]),r[2]),totalBytes:W(parseFloat(r[3]),r[4]),percentComplete:parseFloat(r[5]),speed:W(parseFloat(r[6]),r[7]),eta:l==="-"?0:rn(l)};return{...c,currentFile:c}}let s=e.match(/Transferred:\s+([\d.]+)\s*([A-Za-z]+)\s*\/\s*([\d.]+)\s*([A-Za-z]+),\s*([\d.]+)%/);if(!s)return null;let o=e.match(/([\d.]+)\s*([A-Za-z]+)\/s/),i=e.match(/ETA\s+([^\s]+)$/),a={bytesTransferred:W(parseFloat(s[1]),s[2]),totalBytes:W(parseFloat(s[3]),s[4]),percentComplete:parseFloat(s[5]),speed:o?W(parseFloat(o[1]),o[2]):0,eta:i&&i[1]!=="-"?rn(i[1]):0};return{...a,aggregate:a}}function bt(n){return new Promise((e,t)=>{let r=Oe("rclone",n.args,{stdio:["ignore","pipe","pipe"]}),s="",o=0,i,a,l=c=>{for(let u of c.split(`
|
|
3
|
+
`)){if(u.trim().length===0)continue;let d=_r(u);if(!d)continue;i=d.currentFile??i,a=d.aggregate??a;let m=Date.now();if(!(d.percentComplete>=100)&&m-o<500)continue;o=m;let p=a?{...a,aggregate:a,currentFile:i}:{...d,currentFile:i};n.onProgress?.(p)}};r.stdout.on("data",c=>{l(c.toString())}),r.stderr.on("data",c=>{let u=c.toString();s+=u,l(u)}),r.on("close",async c=>{c===0?e():t(new w(`rclone exited with code ${c}`,s))}),r.on("error",c=>{t(new w(`Failed to start rclone: ${c.message}`,""))})})}async function Be(){return new Promise((n,e)=>{let t=Oe("rclone",["version"]);t.on("error",()=>{e(new Error("rclone is not installed or not in PATH. Please install rclone first: https://rclone.org/install/"))}),t.on("close",r=>{r===0?n():e(new Error("rclone is not installed or not in PATH. Please install rclone first: https://rclone.org/install/"))})})}async function Or(n,e,t,r,s,o){let i=`${n}:${e}`;return bt({args:vr({remoteSource:i,localPath:t,rcloneOptions:s,batchFilePath:r}),remoteSource:i,onProgress:o})}async function sn(n,e,t=[]){let r=`${n}:${e}`;return new Promise((s,o)=>{let i=Oe("rclone",Ur({remoteSource:r,extraArgs:t})),a="",l="";i.stdout.on("data",c=>{a+=c.toString()}),i.stderr.on("data",c=>{l+=c.toString()}),i.on("close",async c=>{if(c===0)try{let u=JSON.parse(a||"[]");if(!Array.isArray(u))throw new Error("rclone lsjson did not return an array");let d=Br(u),m=await Mr({remote:n,files:d.files,directories:d.directories,extraArgs:t});s(m)}catch(u){o(new w(`Failed to parse file listing from ${r}: ${u instanceof Error?u.message:String(u)}`,l))}else o(new w(`Failed to list files from ${r}`,l))}),i.on("error",c=>{o(new w(`Failed to start rclone: ${c.message}`,""))})})}async function on(n){let e=[],t=[];for(let r of n.files)Hr(r)?t.push(r):e.push(r);e.length>0&&(await At.promises.writeFile(n.batchFilePath,`${e.map(r=>r.path).join(`
|
|
5
4
|
`)}
|
|
6
|
-
`,"utf-8"),await
|
|
7
|
-
${this.#
|
|
5
|
+
`,"utf-8"),await Or(n.remote,n.remotePath,n.localPath,n.batchFilePath,n.rcloneOptions,n.onProgress));for(let r of t)await Wr({remote:n.remote,remotePath:n.remotePath,localPath:n.localPath,file:r,rcloneOptions:n.rcloneOptions,onProgress:n.onProgress})}function Br(n){let e=[],t=[];for(let r of n){let s=r;if(typeof s.Path!="string")continue;let o=typeof s.ID=="string"&&s.ID.length>0?s.ID:void 0;if(s.IsDir===!0){t.push({path:b(s.Path),id:o});continue}let i=typeof s.Size=="number"&&Number.isFinite(s.Size)?s.Size:0;e.push({path:b(s.Path),size:i,id:o})}return{files:e,directories:t}}async function Mr(n){let e=Nr(n.directories);if(e.length===0)return n.files;let t=e.map(i=>i[0].path),r=n.files.filter(i=>!t.some(a=>ln(i.path,a))),s=zr(n.directories),o=[];for(let i of e)for(let a of i){if(!a.id)throw new Error(`Cannot preserve duplicate remote folder without a stable rclone folder ID: ${a.path}`);let l=ue(a.path),c=St(l,s);s.add(c),o.push(...await an({remote:n.remote,parentId:a.id,sourcePrefix:a.path,targetPrefix:c,extraArgs:n.extraArgs}))}return[...r,...o]}function Nr(n){let e=new Map;for(let o of n){let i=e.get(o.path)??[];i.push(o),e.set(o.path,i)}let t=Array.from(e.values()).filter(o=>o.length>1).sort((o,i)=>o[0].path.split("/").length-i[0].path.split("/").length),r=[],s=[];for(let o of t){let i=o[0].path;s.some(a=>ln(i,a))||(s.push(i),r.push(o))}return r}function zr(n){let e=new Map;for(let r of n)e.set(r.path,(e.get(r.path)??0)+1);let t=new Set;for(let r of n)(e.get(r.path)??0)>1||t.add(ue(r.path));return t}async function an(n){let e=await Gr({remote:n.remote,parentId:n.parentId,extraArgs:n.extraArgs}),t=new Set,r=[];for(let s of e){if(typeof s.name!="string"||typeof s.id!="string")continue;let o=`${n.sourcePrefix}/${s.name}`,i=`${n.targetPrefix}/${ue(s.name)}`,a=s.mimeType==="application/vnd.google-apps.folder"?St(i,t):yt(i,t);if(t.add(a),s.mimeType==="application/vnd.google-apps.folder"){r.push(...await an({remote:n.remote,parentId:s.id,sourcePrefix:o,targetPrefix:a,extraArgs:n.extraArgs}));continue}r.push({path:o,targetPath:a,size:$r(s.size),id:s.id,requiresIdentityDownload:!0})}return r}function Gr(n){let e=`'${jr(n.parentId)}' in parents and trashed = false`;return new Promise((t,r)=>{let s=Oe("rclone",Lr({remote:n.remote,query:e,extraArgs:n.extraArgs}),{stdio:["ignore","pipe","pipe"]}),o="",i="";s.stdout.on("data",a=>{o+=a.toString()}),s.stderr.on("data",a=>{i+=a.toString()}),s.on("close",a=>{if(a!==0){r(new w(`Failed to query children for Google Drive folder ${n.parentId}`,i));return}try{let l=JSON.parse(o||"[]");if(!Array.isArray(l))throw new Error("rclone backend query did not return an array");t(l)}catch(l){r(new w(`Failed to parse children for Google Drive folder ${n.parentId}: ${l instanceof Error?l.message:String(l)}`,i))}}),s.on("error",a=>{r(new w(`Failed to start rclone: ${a.message}`,""))})})}function $r(n){if(typeof n=="number"&&Number.isFinite(n))return n;if(typeof n=="string"){let e=Number(n);return Number.isFinite(e)?e:0}return 0}function ln(n,e){return n===e||n.startsWith(`${e}/`)}function jr(n){return n.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}function Hr(n){let e=F(n),t=b(n.path);return n.requiresIdentityDownload===!0||e!==t}async function Wr(n){let e=pe.join(n.localPath,F(n.file));if(await At.promises.mkdir(pe.dirname(e),{recursive:!0}),n.file.requiresIdentityDownload===!0){if(!n.file.id)throw new Error(`Cannot preserve duplicate remote file without a stable rclone file ID: ${n.file.path}`);await bt({args:Dr({remote:n.remote,fileId:n.file.id,localTargetPath:e,rcloneOptions:n.rcloneOptions}),remoteSource:`${n.remote}:${n.file.path}`,onProgress:n.onProgress});return}await bt({args:xr({remoteFileSource:`${n.remote}:${Kr(n.remotePath,n.file.path)}`,localTargetPath:e,rcloneOptions:n.rcloneOptions}),remoteSource:`${n.remote}:${n.file.path}`,onProgress:n.onProgress})}function Kr(n,e){let t=n.replace(/\/+$/,""),r=e.replace(/^\/+/,"");return t.length===0?r:`${t}/${r}`}var Me=class{#e;constructor(e){this.#e=e}get displayName(){return`${this.#e.remote}:${this.#e.remotePath}`}async prepare(){await Be()}async listFiles(){return sn(this.#e.remote,this.#e.remotePath,this.#e.rcloneOptions.extraRcloneArgs??[])}resolveLocalFile(e,t){return Le(e,t)}async materializeBatch(e){await on({remote:this.#e.remote,remotePath:this.#e.remotePath,localPath:e.batchDir,batchFilePath:e.batchFilePath,files:e.files,rcloneOptions:this.#e.rcloneOptions,onProgress:e.onProgress})}async shutdown(){}};import Ft from"node:fs/promises";import Et from"node:path";var K=class{#e;constructor(e){this.#e=e}get displayName(){return this.#e.rootPath}async prepare(){let e=await Ft.stat(this.#e.rootPath).catch(()=>null);if(!e||!e.isDirectory())throw new Error(`Local source path is not a readable directory: ${this.#e.rootPath}`)}async listFiles(){let e=[];return await this.#s(this.#e.rootPath,"",e),e.sort((t,r)=>t.path.localeCompare(r.path)),e}resolveLocalFile(e,t){let r=F(e);return{relativePath:r,absolutePath:Et.join(this.#e.rootPath,...e.path.split("/")),fileName:Et.posix.basename(r),size:e.size}}async materializeBatch(e){}async shutdown(){}async#s(e,t,r){let s=await Ft.readdir(e,{withFileTypes:!0});for(let o of s){let i=Et.join(e,o.name),a=t===""?o.name:`${t}/${o.name}`;if(o.isDirectory()){await this.#s(i,a,r);continue}if(!o.isFile())continue;let l=await Ft.stat(i);r.push({path:a,size:l.size})}}};import Ne from"node:fs/promises";import Zr from"node:path";import{spawn as qr}from"node:child_process";var Jr=18e4,Yr=2e3,Qr=3e4,Vr=4e3,q=class{#e;#s;#t=null;#o="";#r=null;#n=!1;constructor(e){this.#e=e,this.#s=e.spawnFn??qr}get isRunning(){return this.#t!==null&&this.#r===null}get daemonOutputTail(){return this.#o}async checkClientInstalled(){await this.#l({args:["list"],failureMessage:"LucidLink client is not installed or not in PATH. Install it from https://www.lucidlink.com/download before running aspect-sync sync lucidlink."})}async start(){if(this.#t)throw new Error("LucidLink daemon already started");let e=["--instance",String(this.#e.instanceId),"daemon","--fs",this.#e.filespace,"--user",this.#e.user,"--mount-point",this.#e.mountPoint,"--root-path",this.#e.cacheRootPath],t=this.#s("lucid",e,{stdio:["pipe","pipe","pipe"]});this.#t=t,t.stdout?.on("data",r=>this.#p(r)),t.stderr?.on("data",r=>this.#p(r)),t.on("exit",r=>{this.#r=r??-1,this.#n||console.error(`LucidLink daemon exited unexpectedly (code ${this.#r}). Recent output:
|
|
6
|
+
${this.#o}`)}),t.on("error",r=>{this.#r=-1,this.#p(Buffer.from(`spawn error: ${r.message}
|
|
8
7
|
`))}),t.stdin?.write(`${this.#e.password}
|
|
9
|
-
`),t.stdin?.end(),await this.#
|
|
10
|
-
${this.#
|
|
11
|
-
`+this.#
|
|
12
|
-
${this.#
|
|
13
|
-
`,{encoding:"utf-8",mode:384}),await Me.chmod(n,384)}function At(n){let e={clientId:n.clientId,accessToken:n.token.access_token,refreshToken:n.token.refresh_token??n.previousRefreshToken,expiresAt:new Date(Date.now()+n.token.expires_in*1e3).toISOString(),tokenType:n.token.token_type};return n.defaultAccountId&&(e.defaultAccountId=n.defaultAccountId),e}async function an(n,e){let t=await n.text();if(!n.ok)throw new Error(`Adobe IMS ${e} failed: ${n.status} ${n.statusText} ${t}`);let s=JSON.parse(t);if(!s.access_token||typeof s.expires_in!="number")throw new Error(`Adobe IMS ${e} returned an invalid token response: ${t}`);return s}var ze=class{#e;#n=null;#t=null;#r=null;#s=new Map;constructor(e){this.#e=e}get displayName(){return`frameio:${this.#e.accountId}/${this.#e.folderId}`}async prepare(){await(await this.#u()).validateFolderAccess({accountId:this.#e.accountId,folderId:this.#e.folderId})}async listFiles(){let e=await this.#u(),t=[];await this.#i({client:e,folderId:this.#e.folderId,relativePrefix:"",files:t}),t.sort((r,s)=>r.path.localeCompare(s.path)),this.#s.clear();for(let r of t)this.#s.set(r.id,r);return t}resolveLocalFile(e,t){return ke(e,t)}async materializeBatch(e){let t={bytesTransferred:0,totalBytes:e.files.reduce((i,o)=>i+o.size,0),startedAt:Date.now()},r=0,s=async()=>{for(;r<e.files.length;){let i=r;r+=1,await this.#a({file:e.files[i],batchDir:e.batchDir,totals:t,onProgress:e.onProgress})}};await Promise.all(Array.from({length:Math.min(this.#e.downloadConcurrency,e.files.length)},()=>s()))}async shutdown(){}async#i(e){let t=await e.client.listFolderChildren({accountId:this.#e.accountId,folderId:e.folderId,pageSize:this.#e.pageSize});for(let r of t){if(r.type==="folder"){let i=r;await this.#i({client:e.client,folderId:i.id,relativePrefix:this.#o(e.relativePrefix,i.name),files:e.files});continue}if(r.type!=="file")continue;let s=yt(r);e.files.push({id:s.id,path:this.#o(e.relativePrefix,s.name),size:s.sizeBytes})}}async#a(e){if(!e.file.id)throw new Error(`Frame.io listing missing file ID for ${e.file.path}`);let t=Zr.join(e.batchDir,w(e.file)),r=this.#s.get(e.file.id),i=await(await this.#u()).getFileWithOriginalMediaLink({accountId:this.#e.accountId,fileId:e.file.id}),o={...i,name:r?.path??i.name,sizeBytes:e.file.size},a=0;await Jt({file:o,outputPath:t,onProgress:l=>{e.totals.bytesTransferred+=Math.max(l-a,0),a=l,e.onProgress?.(this.#c(e.totals))}})}#c(e){let t=Math.max((Date.now()-e.startedAt)/1e3,.001),r=e.bytesTransferred/t,s=Math.max(e.totalBytes-e.bytesTransferred,0);return{bytesTransferred:e.bytesTransferred,totalBytes:e.totalBytes,speed:r,eta:r>0?Math.ceil(s/r):0,percentComplete:e.totalBytes>0?e.bytesTransferred/e.totalBytes*100:100}}#o(e,t){let r=e===""?t:`${e}/${t}`;return b(r)}async#u(){if(this.#r)return await this.#r;this.#r=this.#p();try{return await this.#r}finally{this.#r=null}}async#p(){let e=await Ne();return(!this.#n||this.#t!==e)&&(this.#n=new B({token:e}),this.#t=e),this.#n}};function q(n){switch(n.kind){case"rclone":return new De(n);case"local":return new H(n);case"lucidlink":return new Oe(n);case"frameio":return new ze(n);default:{let e=n;throw new Error(`Unsupported sync source: ${JSON.stringify(e)}`)}}}import*as Ge from"fs/promises";import*as He from"path";var es={".mp4":"video/mp4",".mov":"video/quicktime",".avi":"video/x-msvideo",".mkv":"video/x-matroska",".webm":"video/webm",".wmv":"video/x-ms-wmv",".flv":"video/x-flv",".m4v":"video/x-m4v",".mpg":"video/mpeg",".mpeg":"video/mpeg",".3gp":"video/3gpp",".ts":"video/mp2t",".mts":"video/mp2t",".mxf":"application/mxf",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp",".tiff":"image/tiff",".tif":"image/tiff",".svg":"image/svg+xml",".heic":"image/heic",".heif":"image/heif",".avif":"image/avif",".mp3":"audio/mpeg",".wav":"audio/wav",".aac":"audio/aac",".ogg":"audio/ogg",".flac":"audio/flac",".m4a":"audio/mp4",".wma":"audio/x-ms-wma",".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".rtf":"application/rtf",".json":"application/json",".xml":"application/xml"};function ts(n){let e=He.extname(n).toLowerCase();return es[e]??""}var $e=class n{#e;#n=null;#t=null;#r=!1;#s;#i;#a;constructor(e,t,r,s){this.#e=e,this.#s=t,this.#i=r,this.#a=s}static async create(e){let t=await Ge.stat(e),r=He.basename(e),s=ts(r);return new n(e,t.size,r,s)}get name(){return this.#i}get size(){return this.#s}get type(){return this.#a}async readChunk(e,t){if(!this.#n){this.#t||(this.#t=Ge.open(this.#e,"r"));let i=await this.#t;if(this.#t=null,this.#r)return Buffer.alloc(0);this.#n=i}let r=t-e,s=Buffer.alloc(r);return await this.#n.read(s,0,r,e),s}async close(){this.#r=!0;let e=this.#t;await this.#n?.close(),this.#n=null,e&&await(await e.catch(()=>null))?.close(),this.#t=null}};var ns=new Set(["success","failed","cancelled"]),ln=1e3,rs=250,ss=4*1024*1024,Ft=class{#e;name;constructor(e,t){this.#e=e,this.name=t}get size(){return this.#e.size}get type(){return this.#e.type}readChunk(e,t){return this.#e.readChunk(e,t)}async close(){await this.#e.close?.()}},je=class{#e;#n;#t;#r;#s;constructor(e){this.#e=e.config,this.#n=e.httpClient??new x({apiUrl:e.config.apiUrl,apiKey:e.config.apiKey,edgeWorkerUrl:e.config.edgeWorkerUrl,sessionId:e.config.sessionName}),this.#t=e.createFileReader??(t=>$e.create(t)),this.#r=e.onSnapshot,this.#s=e.analytics}async uploadFiles(e){let t=e.filter(a=>a.preSkipped===!0),r=e.filter(a=>a.preSkipped!==!0);if(r.length===0)return{totalFileCount:e.length,successFileCount:0,skippedFileCount:t.length,failedFileCount:0,cancelledFileCount:0,failedFiles:[]};let s=new ne({httpClient:this.#n,maxConcurrency:this.#e.maxConcurrent,deltaIntervalMs:ln,adaptiveConcurrency:!1,analytics:this.#s}),i=[],o=0;try{let a=s.startGroupUpload({name:`${r.length} files`,type:"files",fileCount:r.length,folderCount:0,topLevelFileCount:r.length,topLevelFolderCount:0,rootDirectoryId:this.#e.directoryId,projectId:this.#e.projectId,totalBytes:r.reduce((c,u)=>c+u.file.size,0),conflictResolutionOverride:"skip"});for(let c of r){let u=await this.#t(c.file.absolutePath),d=u.name===c.file.fileName?u:new Ft(u,c.file.fileName),m=s.startUpload({fileReader:d,directoryId:c.directoryId,projectId:this.#e.projectId,groupId:a,chunkSize:ss});s.addAssetToGroup(a,m),i.push({assetId:m,file:c.file,fileReader:d});let g=Date.now();(i.length===1||i.length===r.length||g-o>=rs)&&(o=g,this.#r?.(s.getSnapshot()))}await this.#i(s);let l=s.getSnapshot();return this.#r?.(l),this.#a({snapshot:l,startedUploads:i,preSkippedCount:t.length})}finally{s.destroy()}}async#i(e){let r=Date.now();for(;Date.now()-r<864e5;){let s=e.getSnapshot();this.#r?.(s);let i=Object.values(s.uploadAssets);if(i.length>0&&i.every(o=>ns.has(o.status)))return;await new Promise(o=>setTimeout(o,ln))}throw new Error("Timed out waiting for upload session to finish")}#a(e){let t=[],r=0,s=0,i=0,o=0;for(let a of e.startedUploads){let l=e.snapshot.uploadAssets[a.assetId];if(!l){i+=1,t.push({fileName:a.file.fileName,relativePath:a.file.relativePath,errorMessage:"Upload state missing from upload engine"});continue}if(l.status==="success"){this.#n.skippedAssetIds.has(a.assetId)?s+=1:r+=1;continue}l.status==="cancelled"?o+=1:i+=1,t.push({fileName:a.file.fileName,relativePath:a.file.relativePath,errorMessage:l.errorMessage})}return{totalFileCount:e.startedUploads.length+e.preSkippedCount,successFileCount:r,skippedFileCount:e.preSkippedCount+s,failedFileCount:i,cancelledFileCount:o,failedFiles:t}}};function cn(n,e){return!e||e.count===1?n:n.filter(t=>is(w(t),e.count)===e.index)}function is(n,e){let t=2166136261;for(let r=0;r<n.length;r+=1)t^=n.charCodeAt(r),t=Math.imul(t,16777619);return(t>>>0)%e}var We=200,qe=class{#e;#n;#t;#r;#s;constructor(e,t,r){this.#e=e,this.#n=t??new x({apiUrl:e.apiUrl,apiKey:e.apiKey,edgeWorkerUrl:e.edgeWorkerUrl,sessionId:e.sessionName}),this.#t=new Te({rootDirectoryId:e.directoryId,httpClient:this.#n}),this.#r=new je({config:e,httpClient:this.#n,onSnapshot:s=>C.updateSnapshot(s),analytics:Ht}),this.#s=r??q(e.source)}async run(){try{await this.#i()}finally{await this.#s.shutdown()}}async runBatched(){try{await this.#a()}finally{await this.#s.shutdown()}}async runCheckOnly(){try{await this.#c()}finally{await this.#s.shutdown()}}async#i(){this.#I("Starting data sync..."),await this.#b();let e=this.#k(this.#F(await this.#o()));if(e.length===0){console.log("No files to sync. Exiting."),await this.#R();return}let t={totalFileCount:0,successFileCount:0,skippedFileCount:0,failedFileCount:0,cancelledFileCount:0,completedByteCount:0},r=[],s={batchNumber:1,files:e,totalSize:this.#g(e)};C.start();try{let o=await this.#C({batch:s,totalBatches:1,overallFilesTotal:e.length,overallBytesTotal:s.totalSize,completedTotals:t,batchDir:this.#e.localTempDir});this.#x(t,r,o,s.totalSize)}finally{C.stop()}let i={...t,failedFiles:r};this.#v({summary:i}),await this.#P(i),this.#M(i)}async#a(){if(!this.#e.batchSizeBytes)throw new Error("Batch size not configured. Use batchSizeBytes in config.");this.#I("Starting batched data sync...",[`Batch size: ${h(this.#e.batchSizeBytes)}`,`Max concurrent chunks: ${this.#e.maxConcurrent}`]),await this.#b();let e=this.#k(this.#F(await this.#o()));if(e.length===0){console.log("No files to sync. Exiting."),await this.#R();return}let t=Ot(e,this.#e.batchSizeBytes);await this.#A(t);let r={totalFileCount:0,successFileCount:0,skippedFileCount:0,failedFileCount:0,cancelledFileCount:0,completedByteCount:0},s=[],i=this.#g(e);C.start();try{for(let a of t){let l=await this.#C({batch:a,totalBatches:t.length,overallFilesTotal:e.length,overallBytesTotal:i,completedTotals:r});this.#x(r,s,l,a.totalSize)}}finally{C.stop()}this.#v({summary:{...r,failedFiles:s},extraLines:[`Batches: ${t.length}`]});let o={...r,failedFiles:s};await this.#P(o),this.#M(o)}async#c(){console.log("Running in check-only mode (no downloads/uploads)..."),await this.#s.prepare(),console.log(`Listing source files from ${this.#s.displayName}...`);let e=await this.#s.listFiles();console.log(`Found ${e.length} source files to check`);let t=this.#k(this.#F(e));if(t.length===0){console.log("No source files to check. Exiting.");return}console.log("Fetching Aspect project summary...");let r=await this.#u();console.log("Fetching existing Aspect files...");let s=await this.#t.listFilesInSubtree({onProgress:o=>this.#f(o)}),i=this.#p(t,s,r);this.#w(i)}async#o(){console.log("Listing all source files...");let e=await this.#s.listFiles();return console.log(`Found ${e.length} files`),console.log(`Total size: ${h(this.#g(e))}`),console.log(""),e}async#u(){return await this.#n.get(`/projects/${this.#e.projectId}`)}#p(e,t,r){let s=e.map(y=>({relativePath:w(y),sizeBytes:this.#y(y.size)})),i=s.filter(y=>y.sizeBytes===null).length,o=t.filter(y=>y.isUploaded),a=t.filter(y=>y.uploadStateKnown&&!y.isUploaded),l=t.filter(y=>!y.uploadStateKnown).length;l>0&&(console.warn(`Warning: ${l} server asset(s) did not include upload status; treating them as uploaded for check comparison.`),console.log(""));let c=this.#l(s),u=this.#U(o),d=new Set([...c.keys(),...u.keys()]),m=0,g=0,p=[],A=[],S=[];for(let y of d){let Se=c.get(y)??[],T=u.get(y)??[],E=new Set,Xe=[];for(let F of Se){if(F.sizeBytes===null){Xe.push(F);continue}let N=T.findIndex((v,Ce)=>!E.has(Ce)&&v.sizeBytes===F.sizeBytes);N>=0?(m+=1,E.add(N)):Xe.push(F)}for(let F of Xe){if(F.sizeBytes===null){let v=T.findIndex((Ce,zn)=>!E.has(zn));v>=0?(E.add(v),g+=1):p.push(F);continue}let N=T.findIndex((v,Ce)=>!E.has(Ce));if(N>=0){let v=T[N];E.add(N),A.push({relativePath:y,remoteSizeBytes:F.sizeBytes,serverSizeBytes:v.sizeBytes,assetId:v.assetId})}else p.push(F)}for(let F=0;F<T.length;F++)E.has(F)||S.push(T[F])}return{totalRemoteCount:e.length,totalServerCount:t.length,projectAssetCount:r.num_assets,projectRootDirectoryId:r.root_directory_id,uploadedServerCount:o.length,unknownUploadStateCount:l,unknownRemoteSizeCount:i,pathOnlyMatchCount:g,existingCount:m,missingFiles:p,sizeMismatches:A,extraUploadedFiles:S,incompleteServerFiles:a}}#l(e){let t=new Map;for(let r of e){let s=b(r.relativePath),i=t.get(s)??[];i.push({...r,relativePath:s}),t.set(s,i)}return t}#U(e){let t=new Map;for(let r of e){let s=b(r.relativePath),i=t.get(s)??[];i.push({...r,relativePath:s}),t.set(s,i)}return t}#y(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:null}#F(e){let t=Pe(e);if(t.changes.length===0)return t.files;let r=t.changes.slice(0,10).map(o=>`${o.sourcePath} -> ${o.targetPath}`).join(`
|
|
14
|
-
`),s=t.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
`),
|
|
8
|
+
`),t.stdin?.end(),await this.#i(),this.#e.cacheSize&&await this.#l({args:["--instance",String(this.#e.instanceId),"config","--set","--local","--DataCache.Size",this.#e.cacheSize],failureMessage:`Failed to set LucidLink DataCache.Size to ${this.#e.cacheSize}`})}async stop(){let e=this.#t;if(!e||this.#r!==null){this.#t=null;return}this.#n=!0,await this.#l({args:["--instance",String(this.#e.instanceId),"exit"],failureMessage:"Failed to request LucidLink daemon exit"}).catch(t=>{console.error(t.message)}),await this.#u(e),this.#t=null}assertHealthy(){if(this.#t&&this.#r!==null&&!this.#n)throw new Error(`LucidLink daemon exited unexpectedly (code ${this.#r}). Recent output:
|
|
9
|
+
${this.#o}`)}async#i(){let e=this.#e.linkTimeoutMs??Jr,t=this.#e.linkPollIntervalMs??Yr,r=Date.now();for(;Date.now()-r<e;){if(this.#r!==null)throw new Error(`LucidLink daemon exited before linking (code ${this.#r}). Check the filespace name and credentials. Recent output:
|
|
10
|
+
`+this.#o);let s=await this.#c();if(s!==null&&/\bLinked\b/i.test(s))return;await Xr(t)}throw new Error(`Timed out after ${Math.round(e/1e3)}s waiting for LucidLink filespace "${this.#e.filespace}" to link. Recent daemon output:
|
|
11
|
+
${this.#o}`)}async#c(){return new Promise(e=>{let t=this.#s("lucid",["--instance",String(this.#e.instanceId),"status"],{stdio:["ignore","pipe","pipe"]}),r="";t.stdout?.on("data",s=>{r+=s.toString()}),t.on("exit",s=>{e(s===0?r:null)}),t.on("error",()=>{e(null)})})}#l(e){return new Promise((t,r)=>{let s=this.#s("lucid",e.args,{stdio:["ignore","pipe","pipe"]}),o="";s.stderr?.on("data",i=>{o+=i.toString()}),s.on("exit",i=>{i===0?t():r(new Error(`${e.failureMessage} (exit code ${i}): ${o.trim()}`))}),s.on("error",i=>{r(new Error(`${e.failureMessage}: ${i.message}`))})})}async#u(e){this.#r===null&&await new Promise(t=>{let r=setTimeout(()=>{e.kill("SIGKILL")},Qr);e.on("exit",()=>{clearTimeout(r),t()}),this.#r!==null&&(clearTimeout(r),t())})}#p(e){this.#o=(this.#o+e.toString()).slice(-Vr)}};function Xr(n){return new Promise(e=>setTimeout(e,n))}var ze=class{#e;#s;#t;constructor(e,t){this.#e=e,this.#s=t??new q({filespace:e.filespace,user:e.user,password:e.password,instanceId:e.instanceId,mountPoint:e.mountPoint,cacheRootPath:e.cacheRootPath,cacheSize:e.cacheSize}),this.#t=new K({kind:"local",rootPath:this.#o()})}get displayName(){let e=this.#e.filespacePath===""?"":`/${this.#e.filespacePath}`;return`lucidlink:${this.#e.filespace}${e}`}async prepare(){await this.#s.checkClientInstalled(),await Ne.mkdir(this.#e.mountPoint,{recursive:!0}),await Ne.mkdir(this.#e.cacheRootPath,{recursive:!0}),console.log(`Mounting LucidLink filespace ${this.#e.filespace} at ${this.#e.mountPoint}...`),await this.#s.start(),console.log("Filespace linked and mounted");let e=await Ne.stat(this.#o()).catch(()=>null);if(!e||!e.isDirectory())throw new Error(`Path "${this.#e.filespacePath}" does not exist in filespace ${this.#e.filespace}`)}async listFiles(){return this.#s.assertHealthy(),this.#t.listFiles()}resolveLocalFile(e,t){return this.#t.resolveLocalFile(e,t)}async materializeBatch(e){this.#s.assertHealthy(),await this.#t.materializeBatch(e)}async shutdown(){await this.#s.stop(),await Ne.rm(this.#e.workDir,{recursive:!0,force:!0})}#o(){return this.#e.filespacePath===""?this.#e.mountPoint:Zr.join(this.#e.mountPoint,...this.#e.filespacePath.split("/"))}};import bs from"node:path";import cn from"node:fs";import es from"node:path";var ts="https://api.frame.io/v4",ns="https://api.frame.io",me=4,rs=1e3,ss=15e3,z=class{#e;constructor(e){this.#e=e.token}async listAccounts(){return(await this.#s("/accounts")).data}async listWorkspaces(e){return(await this.#s(`/accounts/${e}/workspaces`)).data}async listProjects(e){let t=[],r=`/accounts/${e.accountId}/workspaces/${e.workspaceId}/projects`,s={page_size:String(e.pageSize??100)};for(;r;){let o=await this.#s(r,s);t.push(...o.data),r=o.links?.next??null,s=void 0}return t}async listAccountProjects(e){let t=[],r=`/accounts/${e.accountId}/projects`,s={page_size:String(e.pageSize??100)};for(;r;){let o=await this.#s(r,s,{"api-version":"experimental"});t.push(...o.data),r=o.links?.next??null,s=void 0}return t}async getProject(e){let t=await this.#s(`/accounts/${e.accountId}/projects/${e.projectId}`);return"data"in t&&t.data?t.data:t}async listFolderChildren(e){let t=[],r=`/accounts/${e.accountId}/folders/${e.folderId}/children`,s={page_size:String(e.pageSize),type:"file,folder,version_stack",...e.includeOriginalMediaLinks?{include:"media_links.original"}:{}};for(;r;){let o=await this.#s(r,s);t.push(...o.data),r=o.links?.next??null,s=void 0}return t}async validateFolderAccess(e){await this.#s(`/accounts/${e.accountId}/folders/${e.folderId}/children`,{page_size:"1"})}async getFileWithOriginalMediaLink(e){let t=await this.#s(`/accounts/${e.accountId}/files/${e.fileId}`,{include:"media_links.original"}),r="data"in t&&t.data?t.data:t;return It(r)}async#s(e,t,r={}){let s=os(e);for(let[o,i]of Object.entries(t??{}))s.searchParams.set(o,i);for(let o=0;o<me;o+=1)try{let i=await fetch(s,{headers:{Authorization:`Bearer ${this.#e}`,Accept:"application/json",...r}});if(!i.ok){let a=await i.text().catch(()=>"");if(ls(i)&&o<me-1){await wt(Ge(i.headers.get("retry-after"),o));continue}throw new Error(`Frame.io API ${i.status} ${i.statusText} for ${s.pathname}: ${a}`)}return await i.json()}catch(i){if(dn(i)&&o<me-1){await wt(Ge(null,o));continue}throw i}throw new Error(`Frame.io API request failed for ${s.pathname}`)}};function os(n){return n.startsWith("http")?new URL(n):n.startsWith("/v4/")?new URL(`${ns}${n}`):new URL(`${ts}${n}`)}function It(n){return{id:n.id,name:n.name??n.id,sizeBytes:is(n),downloadUrl:n.media_links?.original?.download_url??void 0}}function is(n){let e=[n.file_size,n.filesize,n.size,n.size_bytes,n.bytes];for(let t of e){if(typeof t=="number"&&Number.isFinite(t))return t;if(typeof t=="string"){let r=Number(t);if(Number.isFinite(r))return r}}return 0}async function un(n){if(!n.file.downloadUrl)throw new Error(`Frame.io file ${n.file.id} has no original download URL`);for(let e=0;e<me;e+=1)try{return await as(n)}catch(t){if(cs(t)&&e<me-1){await wt(ds(t,e));continue}throw t}throw new Error(`Download failed for ${n.file.name}`)}async function as(n){if(!n.file.downloadUrl)throw new Error(`Frame.io file ${n.file.id} has no original download URL`);let e=new AbortController,t=n.maxSeconds===void 0?null:setTimeout(()=>e.abort(),n.maxSeconds*1e3),r=null,s=Date.now(),o=0;try{n.outputPath&&(await cn.promises.mkdir(es.dirname(n.outputPath),{recursive:!0}),r=cn.createWriteStream(n.outputPath));let a=await fetch(n.file.downloadUrl,{signal:e.signal,headers:{Accept:"application/octet-stream"}});if(!a.ok||!a.body){let c=await a.text().catch(()=>"");throw new he(`Download failed for ${n.file.name}: ${a.status} ${a.statusText} ${c}`,a.status,a.headers.get("retry-after"))}let l=a.body.getReader();for(;;){let{done:c,value:u}=await l.read();if(c)break;o+=u.byteLength,n.onProgress?.(o),r&&await ms(r,u)}}catch(a){if(a.name!=="AbortError")throw a}finally{t&&clearTimeout(t),r&&await hs(r)}let i=Math.max((Date.now()-s)/1e3,.001);return{id:n.file.id,name:n.file.name,bytesRead:o,seconds:i,outputPath:n.outputPath}}var he=class extends Error{status;retryAfter;constructor(e,t,r){super(e),this.status=t,this.retryAfter=r}};function ls(n){return n.status===408||n.status===425||n.status===429||n.status>=500}function cs(n){return n instanceof he?us(n.status):dn(n)}function us(n){return n===408||n===425||n===429||n>=500}function dn(n){if(!(n instanceof Error)||n.name==="AbortError")return!1;if(n instanceof TypeError)return!0;let e=n.code;return e==="ECONNRESET"||e==="ETIMEDOUT"||e==="UND_ERR_SOCKET"}function ds(n,e){return n instanceof he?Ge(n.retryAfter,e):Ge(null,e)}function Ge(n,e){let t=ps(n);return t!==null?t:Math.min(rs*2**e,ss)}function ps(n){if(!n)return null;let e=Number(n);if(Number.isFinite(e))return Math.max(e*1e3,0);let t=Date.parse(n);return Number.isFinite(t)?Math.max(t-Date.now(),0):null}function wt(n){return new Promise(e=>setTimeout(e,n))}function ms(n,e){return new Promise((t,r)=>{if(n.write(e)){t();return}n.once("drain",t),n.once("error",r)})}function hs(n){return new Promise((e,t)=>{n.end(e),n.once("error",t)})}import Pt from"node:crypto";import $e from"node:fs/promises";import fs from"node:os";import pn from"node:path";var gs="https://ims-na1.adobelogin.com/ims/authorize/v2",mn="https://ims-na1.adobelogin.com/ims/token/v3",ys="eac24c58b3bb4e8ab26105ad17adf779",Ss=300*1e3;function hn(){return process.env.FRAMEIO_CLIENT_ID||ys}function J(){return pn.join(fs.homedir(),".config","aspect-sync","frameio-auth.json")}function fn(){let n=Pt.randomBytes(32).toString("base64url"),e=Pt.createHash("sha256").update(n).digest("base64url");return{verifier:n,challenge:e}}function gn(n){let e=new URL(gs);return e.searchParams.set("client_id",n.clientId),e.searchParams.set("scope","openid email profile offline_access additional_info.roles"),e.searchParams.set("response_type","code"),e.searchParams.set("code_challenge",n.codeChallenge),e.searchParams.set("code_challenge_method","S256"),e.searchParams.set("state",n.state??Pt.randomBytes(16).toString("hex")),e.toString()}function yn(n){let e=n.trim();if(!e)throw new Error("Authorization code cannot be empty");if(!e.includes("code="))return e;let r=new URL(e).searchParams.get("code");if(!r)throw new Error("Redirect URL did not include a code parameter");return r}async function Sn(n){let e=await fetch(`${mn}?client_id=${encodeURIComponent(n.clientId)}`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({code:n.code,grant_type:"authorization_code",code_verifier:n.codeVerifier})});return Cn(e,"authorization code exchange")}async function Cs(n){let e=await fetch(`${mn}?client_id=${encodeURIComponent(n.clientId)}`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:n.refreshToken})});return Cn(e,"refresh token exchange")}async function je(){let n=J(),e=await Rt(n),t=Date.parse(e.expiresAt);if(Number.isFinite(t)&&t-Date.now()>Ss)return e.accessToken;if(!e.refreshToken)throw new Error(`Frame.io auth file ${n} has no refresh token; run aspect-sync frameio login`);let r=await Cs({clientId:e.clientId,refreshToken:e.refreshToken}),s=kt({clientId:e.clientId,token:r,previousRefreshToken:e.refreshToken,defaultAccountId:e.defaultAccountId});return await Tt(n,s),s.accessToken}async function Rt(n){let e=await $e.readFile(n,"utf-8").catch(t=>{throw t.code==="ENOENT"?new Error(`Frame.io auth file not found at ${n}; run aspect-sync frameio login`):t});return JSON.parse(e)}async function Tt(n,e){await $e.mkdir(pn.dirname(n),{recursive:!0}),await $e.writeFile(n,`${JSON.stringify(e,null,2)}
|
|
12
|
+
`,{encoding:"utf-8",mode:384}),await $e.chmod(n,384)}function kt(n){let e={clientId:n.clientId,accessToken:n.token.access_token,refreshToken:n.token.refresh_token??n.previousRefreshToken,expiresAt:new Date(Date.now()+n.token.expires_in*1e3).toISOString(),tokenType:n.token.token_type};return n.defaultAccountId&&(e.defaultAccountId=n.defaultAccountId),e}async function Cn(n,e){let t=await n.text();if(!n.ok)throw new Error(`Adobe IMS ${e} failed: ${n.status} ${n.statusText} ${t}`);let s=JSON.parse(t);if(!s.access_token||typeof s.expires_in!="number")throw new Error(`Adobe IMS ${e} returned an invalid token response: ${t}`);return s}var He=class{#e;#s=null;#t=null;#o=null;#r=new Map;constructor(e){this.#e=e}get displayName(){return`frameio:${this.#e.accountId}/${this.#e.folderId}`}async prepare(){await(await this.#u()).validateFolderAccess({accountId:this.#e.accountId,folderId:this.#e.folderId})}async listFiles(){let e=await this.#u(),t=[];await this.#n({client:e,folderId:this.#e.folderId,relativePrefix:"",files:t}),t.sort((r,s)=>r.path.localeCompare(s.path)),this.#r.clear();for(let r of t)this.#r.set(r.id,r);return t}resolveLocalFile(e,t){return Le(e,t)}async materializeBatch(e){let t={bytesTransferred:0,totalBytes:e.files.reduce((o,i)=>o+i.size,0),startedAt:Date.now()},r=0,s=async()=>{for(;r<e.files.length;){let o=r;r+=1,await this.#i({file:e.files[o],batchDir:e.batchDir,totals:t,onProgress:e.onProgress})}};await Promise.all(Array.from({length:Math.min(this.#e.downloadConcurrency,e.files.length)},()=>s()))}async shutdown(){}async#n(e){let t=await e.client.listFolderChildren({accountId:this.#e.accountId,folderId:e.folderId,pageSize:this.#e.pageSize});for(let r of t){if(r.type==="folder"){let o=r;await this.#n({client:e.client,folderId:o.id,relativePrefix:this.#l(e.relativePrefix,o.name),files:e.files});continue}if(r.type!=="file")continue;let s=It(r);e.files.push({id:s.id,path:this.#l(e.relativePrefix,s.name),size:s.sizeBytes})}}async#i(e){if(!e.file.id)throw new Error(`Frame.io listing missing file ID for ${e.file.path}`);let t=bs.join(e.batchDir,F(e.file)),r=this.#r.get(e.file.id),o=await(await this.#u()).getFileWithOriginalMediaLink({accountId:this.#e.accountId,fileId:e.file.id}),i={...o,name:r?.path??o.name,sizeBytes:e.file.size},a=0;await un({file:i,outputPath:t,onProgress:l=>{e.totals.bytesTransferred+=Math.max(l-a,0),a=l,e.onProgress?.(this.#c(e.totals))}})}#c(e){let t=Math.max((Date.now()-e.startedAt)/1e3,.001),r=e.bytesTransferred/t,s=Math.max(e.totalBytes-e.bytesTransferred,0);return{bytesTransferred:e.bytesTransferred,totalBytes:e.totalBytes,speed:r,eta:r>0?Math.ceil(s/r):0,percentComplete:e.totalBytes>0?e.bytesTransferred/e.totalBytes*100:100}}#l(e,t){let r=e===""?t:`${e}/${t}`;return b(r)}async#u(){if(this.#o)return await this.#o;this.#o=this.#p();try{return await this.#o}finally{this.#o=null}}async#p(){let e=await je();return(!this.#s||this.#t!==e)&&(this.#s=new z({token:e}),this.#t=e),this.#s}};function Y(n){switch(n.kind){case"rclone":return new Me(n);case"local":return new K(n);case"lucidlink":return new ze(n);case"frameio":return new He(n);default:{let e=n;throw new Error(`Unsupported sync source: ${JSON.stringify(e)}`)}}}import*as Ke from"fs/promises";import*as qe from"path";var As={".mp4":"video/mp4",".mov":"video/quicktime",".avi":"video/x-msvideo",".mkv":"video/x-matroska",".webm":"video/webm",".wmv":"video/x-ms-wmv",".flv":"video/x-flv",".m4v":"video/x-m4v",".mpg":"video/mpeg",".mpeg":"video/mpeg",".3gp":"video/3gpp",".ts":"video/mp2t",".mts":"video/mp2t",".mxf":"application/mxf",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp",".tiff":"image/tiff",".tif":"image/tiff",".svg":"image/svg+xml",".heic":"image/heic",".heif":"image/heif",".avif":"image/avif",".mp3":"audio/mpeg",".wav":"audio/wav",".aac":"audio/aac",".ogg":"audio/ogg",".flac":"audio/flac",".m4a":"audio/mp4",".wma":"audio/x-ms-wma",".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".rtf":"application/rtf",".json":"application/json",".xml":"application/xml"};function Fs(n){let e=qe.extname(n).toLowerCase();return As[e]??""}var We=class n{#e;#s=null;#t=null;#o=!1;#r;#n;#i;constructor(e,t,r,s){this.#e=e,this.#r=t,this.#n=r,this.#i=s}static async create(e){let t=await Ke.stat(e),r=qe.basename(e),s=Fs(r);return new n(e,t.size,r,s)}get name(){return this.#n}get size(){return this.#r}get type(){return this.#i}async readChunk(e,t){if(!this.#s){this.#t||(this.#t=Ke.open(this.#e,"r"));let o=await this.#t;if(this.#t=null,this.#o)return Buffer.alloc(0);this.#s=o}let r=t-e,s=Buffer.alloc(r);return await this.#s.read(s,0,r,e),s}async close(){this.#o=!0;let e=this.#t;await this.#s?.close(),this.#s=null,e&&await(await e.catch(()=>null))?.close(),this.#t=null}};var Es=new Set(["success","failed","cancelled"]),bn=1e3,ws=250,Is=4*1024*1024,vt=class{#e;name;constructor(e,t){this.#e=e,this.name=t}get size(){return this.#e.size}get type(){return this.#e.type}readChunk(e,t){return this.#e.readChunk(e,t)}async close(){await this.#e.close?.()}},Je=class{#e;#s;#t;#o;#r;constructor(e){this.#e=e.config,this.#s=e.httpClient??new x({apiUrl:e.config.apiUrl,apiKey:e.config.apiKey,edgeWorkerUrl:e.config.edgeWorkerUrl,sessionId:e.config.sessionName}),this.#t=e.createFileReader??(t=>We.create(t)),this.#o=e.onSnapshot,this.#r=e.analytics}async uploadFiles(e){let t=e.filter(a=>a.preSkipped===!0),r=e.filter(a=>a.preSkipped!==!0);if(r.length===0)return{totalFileCount:e.length,successFileCount:0,skippedFileCount:t.length,failedFileCount:0,cancelledFileCount:0,failedFiles:[]};let s=new ae({httpClient:this.#s,maxConcurrency:this.#e.maxConcurrent,deltaIntervalMs:bn,adaptiveConcurrency:!1,analytics:this.#r}),o=[],i=0;try{let a=s.startGroupUpload({name:`${r.length} files`,type:"files",fileCount:r.length,folderCount:0,topLevelFileCount:r.length,topLevelFolderCount:0,rootDirectoryId:this.#e.directoryId,projectId:this.#e.projectId,totalBytes:r.reduce((c,u)=>c+u.file.size,0),conflictResolutionOverride:"skip"});for(let c of r){let u=await this.#t(c.file.absolutePath),d=u.name===c.file.fileName?u:new vt(u,c.file.fileName),m=s.startUpload({fileReader:d,directoryId:c.directoryId,projectId:this.#e.projectId,groupId:a,chunkSize:Is});s.addAssetToGroup(a,m),o.push({assetId:m,file:c.file,fileReader:d});let f=Date.now();(o.length===1||o.length===r.length||f-i>=ws)&&(i=f,this.#o?.(s.getSnapshot()))}await this.#n(s);let l=s.getSnapshot();return this.#o?.(l),this.#i({snapshot:l,startedUploads:o,preSkippedCount:t.length})}finally{s.destroy()}}async#n(e){let r=Date.now();for(;Date.now()-r<864e5;){let s=e.getSnapshot();this.#o?.(s);let o=Object.values(s.uploadAssets);if(o.length>0&&o.every(i=>Es.has(i.status)))return;await new Promise(i=>setTimeout(i,bn))}throw new Error("Timed out waiting for upload session to finish")}#i(e){let t=[],r=0,s=0,o=0,i=0;for(let a of e.startedUploads){let l=e.snapshot.uploadAssets[a.assetId];if(!l){o+=1,t.push({fileName:a.file.fileName,relativePath:a.file.relativePath,errorMessage:"Upload state missing from upload engine"});continue}if(l.status==="success"){this.#s.skippedAssetIds.has(a.assetId)?s+=1:r+=1;continue}l.status==="cancelled"?i+=1:o+=1,t.push({fileName:a.file.fileName,relativePath:a.file.relativePath,errorMessage:l.errorMessage})}return{totalFileCount:e.startedUploads.length+e.preSkippedCount,successFileCount:r,skippedFileCount:e.preSkippedCount+s,failedFileCount:o,cancelledFileCount:i,failedFiles:t}}};var h=(n,e=2)=>{if(n===0)return"0 B";let t=1e3,r=e<0?0:e,s=["B","KB","MB","GB","TB","PB","EB"],o=Math.floor(Math.log(n)/Math.log(t));return`${(n/Math.pow(t,o)).toFixed(r)} ${s[o]}`},Ye=n=>{if(n===null)return null;let t=n*8/(1e3*1e3);return t<1?`${(t*1e3).toFixed(0)} Kbps`:`${t.toFixed(1)} Mbps`},fe=n=>{if(n===null)return null;let e=Math.floor(n/3600),t=Math.floor(n%3600/60),r=Math.floor(n%60);return e>0?`${e}h ${t}m`:t>0?`${t}m ${r}s`:`${r}s`};function An(n,e){return!e||e.count===1?n:n.filter(t=>Ps(F(t),e.count)===e.index)}function Ps(n,e){let t=2166136261;for(let r=0;r<n.length;r+=1)t^=n.charCodeAt(r),t=Math.imul(t,16777619);return(t>>>0)%e}import g from"chalk";import Fn from"log-update";var Rs=1e3,Ut=class{#e=null;#s=!1;#t=null;#o=null;#r=null;#n=new Map;#i=null;#c=null;#l=null;#u=null;start(){this.#s||(this.#s=!0,this.#n.clear(),this.#i=null,this.#c=null,this.#l=null,this.#u=null,this.#e=setInterval(()=>this.render(),Rs))}stop(){this.#s&&(this.#s=!1,this.#e&&(clearInterval(this.#e),this.#e=null),this.render(),Fn.done())}updateSnapshot(e){this.#t=e}updateBatchState(e){this.#o=e}updateDownloadProgress(e){if(!e){this.#r=null;return}let t=e.percentComplete>=100||e.bytesTransferred>=e.totalBytes;!t&&e.speed>0&&(this.#l=e),this.#r=t&&this.#l?{...e,speed:this.#l.speed,eta:this.#l.eta}:e}persistCurrentBatchLine(){!this.#o||this.#o.currentPhase!=="complete"||this.#n.set(this.#o.currentBatch,this.#g(this.#o))}resetUploadSnapshot(){this.#t=null,this.#r=null,this.#l=null,this.#u=null}render(){if(!this.#s)return;let e=this.#o?this.#k(this.#o):this.#a();Fn(e.join(`
|
|
13
|
+
`))}#p(e,t){let r=[`${g.green(h(t.bytesTransferred))} / ${g.gray(h(t.totalBytes))}`,g.cyan(`${t.percentComplete.toFixed(1)}%`),g.magenta(Ye(t.speed)??"..."),`${g.yellow("ETA")}: ${g.yellow(fe(t.eta)??"...")}`];return`${g.blue(e)}: ${r.join(" | ")}`}#a(){let e=this.#y();return[this.#R(e),this.#m(e)]}#k(e){let t=[];for(let r=1;r<e.currentBatch;r++){let s=this.#n.get(r);s&&t.push(s)}return t.push(this.#g(e)),t.push(this.#C(e)),t}#g(e){let t=`Batch ${e.currentBatch}/${e.totalBatches}`;switch(e.currentPhase){case"downloading":return this.#r?this.#I(t,this.#r):`${t}: ${g.blue("Downloading...")}`;case"scanning":return`${t}: ${g.yellow(e.extraDetails??"Scanning...")}`;case"syncing_folders":return`${t}: ${g.yellow(e.extraDetails??"Syncing folders...")}`;case"uploading":return this.#P(t,e);case"cleaning":return`${t}: ${g.yellow("Cleaning...")}`;case"complete":return`${t}: ${g.green("Complete")} (${e.batchFilesTotal} files, ${h(e.batchBytesTotal)}${e.extraDetails?`, ${e.extraDetails}`:""})`}}#I(e,t){let r=[`${e}: ${this.#p("Downloading batch",t.aggregate??t)}`];return t.currentFile&&r.push(this.#p("Downloading current file",t.currentFile)),r.join(`
|
|
14
|
+
`)}#P(e,t){let r=this.#y(),s=r.successFileCount+r.failedFileCount+r.cancelledFileCount,o=Math.max(t.batchFilesTotal-t.batchFilesSkipped,0),i=Math.max(t.batchBytesTotal-t.batchBytesSkipped,0),a=i>0?(r.uploadedBytes/i*100).toFixed(1):"0.0",l=this.#E(t,r,i),c=l?.formattedSpeed??null,u=l?.formattedTime??null,d=r.totalFileCount>0&&r.totalFileCount<o?`, ${g.gray(`Enqueued: ${r.totalFileCount}/${o}`)}`:"",m=c&&u?`, ${c}, ETA: ${u}`:"",f=t.batchFilesSkipped>0?`, ${g.yellow(`Skipped: ${t.batchFilesSkipped} files / ${h(t.batchBytesSkipped)}`)}`:"",p=i>0&&r.uploadedBytes>=i&&s<o?"Finalizing":"Uploading";return`${e}: ${g.blue(p)} (${s}/${o} files, ${h(r.uploadedBytes)} / ${h(i)}, ${a}%${d}${m}${f})`}#C(e){let t=this.#y(),r=e.batchFilesSkipped+t.successFileCount+t.failedFileCount+t.cancelledFileCount,s=e.batchBytesSkipped+t.uploadedBytes,o=e.overallFilesCompleted+r,i=e.overallBytesCompleted+s,a=Math.max(e.overallBytesTotal-i,0),l=this.#h(e),c=this.#b(e,t),u=l!==null&&c!==null?l+c:null;return[`Completed: ${o}/${e.overallFilesTotal} files`,`${h(i)} / ${h(e.overallBytesTotal)}`,g.yellow(`${h(a)} remaining`),`Download ETA: ${fe(l)??"..."}`,`Upload ETA: ${fe(c)??"..."}`,`Total ETA: ${fe(u)??"..."}`].join(", ")}#h(e){let t=e.overallBytesCompleted+e.batchBytesSkipped+(this.#r?.bytesTransferred??0),r=Math.max(e.overallBytesTotal-t,0);if(r===0)return e.currentPhase==="downloading"&&this.#r?(this.#i=this.#r.eta,this.#r.eta):(this.#i=0,0);if(this.#r&&this.#r.speed>0){let s=Math.ceil(r/this.#r.speed);return this.#i=s,s}return e.currentPhase==="uploading"||e.currentPhase==="cleaning"||e.currentPhase==="complete"?(this.#i=0,0):this.#i}#b(e,t){let r=e.overallBytesCompleted+e.batchBytesSkipped+t.uploadedBytes,s=Math.max(e.overallBytesTotal-r,0),o=Math.max(e.batchBytesTotal-e.batchBytesSkipped,0),i=this.#E(e,t,o);if(s===0)return e.currentPhase==="uploading"&&i?(this.#c=i.timeRemainingSeconds,i.timeRemainingSeconds):(this.#c=0,0);if(i&&i.uploadSpeedMbps>0){let a=i.uploadSpeedMbps*1024*1024/8,l=Math.ceil(s/a);return this.#c=l,l}return this.#c}#E(e,t,r){let s=this.#t?.uploadStats,o=r>0&&t.uploadedBytes>=r;return s&&s.uploadSpeedMbps>0&&s.formattedSpeed!=="Calculating..."&&!o?(this.#u={uploadSpeedMbps:s.uploadSpeedMbps,formattedSpeed:s.formattedSpeed,formattedTime:s.formattedTime,timeRemainingSeconds:s.timeRemainingSeconds},this.#u):e.currentPhase==="uploading"&&o&&this.#u?this.#u:s?{uploadSpeedMbps:s.uploadSpeedMbps,formattedSpeed:s.formattedSpeed,formattedTime:s.formattedTime,timeRemainingSeconds:s.timeRemainingSeconds}:null}#R(e){return[`Total: ${e.totalFileCount}`,g.green(`Success: ${e.successFileCount}`),g.red(`Failed: ${e.failedFileCount}`),g.red(`Cancelled: ${e.cancelledFileCount}`),g.blue(`Active: ${e.activeFileCount}`),g.gray(`Queued: ${e.queuedFileCount}`)].join(" | ")}#m(e){let t=Math.max(e.totalBytes-e.uploadedBytes,0),r=this.#t?` | ${g.cyan(`Speed: ${this.#t.uploadStats.formattedSpeed}`)} | ${g.magenta(`Time remaining: ${this.#t.uploadStats.formattedTime}`)}`:"";return[`Total: ${h(e.totalBytes)}`,g.green(`Uploaded: ${h(e.uploadedBytes)}`),g.yellow(`Remaining: ${h(t)}`)].join(" | ")+r}#y(){return this.#t?Object.values(this.#t.uploadAssets).reduce((t,r)=>{switch(t.totalFileCount+=1,t.totalBytes+=r.totalBytesToUpload,t.uploadedBytes+=r.status==="success"?r.totalBytesToUpload:r.bytesUploaded,r.status){case"success":t.successFileCount+=1;break;case"failed":t.failedFileCount+=1;break;case"cancelled":t.cancelledFileCount+=1;break;case"in-progress":t.activeFileCount+=1;break;default:t.queuedFileCount+=1;break}return t},{totalFileCount:0,successFileCount:0,failedFileCount:0,cancelledFileCount:0,activeFileCount:0,queuedFileCount:0,uploadedBytes:0,totalBytes:0}):{totalFileCount:0,successFileCount:0,failedFileCount:0,cancelledFileCount:0,activeFileCount:0,queuedFileCount:0,uploadedBytes:0,totalBytes:0}}},P=new Ut;var Qe=class{#e;#s;#t;#o="sync";#r=null;#n=null;#i=null;#c=null;#l=null;#u;#p=[];#a=null;#k=null;constructor(e){this.#e=e.config,this.#s=e.sourceDisplayName,this.#t=e.writeJsonLine??(t=>{process.stdout.write(`${t}
|
|
15
|
+
`)})}get isJsonMode(){return this.#e.progressMode==="json"}start({kind:e,title:t,extraLines:r=[],humanMode:s="banner"}){if(this.#o=e,!this.isJsonMode){if(s==="message"){console.log(t);return}console.log(t),console.log(`Session: ${this.#e.sessionName}`),console.log(`Source: ${this.#s}`),console.log(`Root directory ID: ${this.#e.directoryId}`),console.log(`Project ID: ${this.#e.projectId}`),console.log(`Temp directory: ${this.#e.localTempDir}`),console.log(`Edge worker URL: ${this.#e.edgeWorkerUrl}`),console.log(`Shard: ${this.#L()}`);for(let o of r)console.log(o);console.log("");return}this.#h({jobId:this.#e.sessionName,type:"start",emittedAt:new Date().toISOString(),sessionName:this.#e.sessionName,sourceDisplayName:this.#s,aspectProjectId:this.#e.projectId,aspectDirectoryId:this.#e.directoryId,tempDir:this.#e.localTempDir,edgeWorkerUrl:this.#e.edgeWorkerUrl,message:[t,...r].join(" ").trim()||void 0,snapshot:this.#b({status:"running"})})}log(e){if(!this.isJsonMode){console.log(e);return}this.#I(e)}warn(e){if(!this.isJsonMode){console.warn(e);return}this.#I(e)}blank(){this.isJsonMode||console.log("")}startLiveDisplay(){this.isJsonMode||P.start()}stopLiveDisplay(){this.isJsonMode||P.stop()}updateBatchState(e){if(this.#r=e,!this.isJsonMode){P.updateBatchState(e);return}this.#P(e.extraDetails)}updateDownloadProgress(e){if(this.#i=e,!this.isJsonMode){P.updateDownloadProgress(e);return}e&&this.#P()}updateUploadSnapshot(e){if(this.#n=e,!this.isJsonMode){P.updateSnapshot(e);return}this.#P()}resetUploadSnapshot(){this.#n=null,this.#i=null,this.isJsonMode||(P.resetUploadSnapshot(),P.updateDownloadProgress(null))}persistCurrentBatchLine(){if(!this.#r||this.#r.currentPhase!=="complete")return;let e={batchNumber:this.#r.currentBatch,filesCompleted:this.#r.batchFilesTotal,bytesCompleted:this.#r.batchBytesTotal},t=this.#p.findIndex(r=>r.batchNumber===e.batchNumber);if(t===-1?this.#p.push(e):this.#p[t]=e,!this.isJsonMode){P.persistCurrentBatchLine();return}this.#h({jobId:this.#e.sessionName,type:"batch_complete",emittedAt:new Date().toISOString(),batch:e,snapshot:this.#b({status:"running"})})}recordSourceListing({files:e,humanDescription:t="files",includeHumanTotal:r=!0}){this.#c=e.length,this.#l=Ts(e),this.isJsonMode||(console.log(`Found ${this.#c} ${t}`),r&&console.log(`Total size: ${h(this.#l)}`),console.log("")),this.#g()}recordPathRenameWarnings(e){if(this.#u=e,!this.isJsonMode){let t=e.sample.map(o=>`${o.sourcePath} -> ${o.targetPath}`).join(`
|
|
16
|
+
`),r=e.count-e.sample.length,s=r>0?`
|
|
17
|
+
...and ${r} more renamed target path(s)`:"";console.warn(`Warning: ${e.count} remote file path(s) were renamed for Aspect compatibility.
|
|
18
|
+
${t}${s}
|
|
19
|
+
`),console.log("")}this.#g()}printSummary({summary:e,extraLines:t=[]}){if(!this.isJsonMode){console.log(""),console.log("=".repeat(60)),console.log("Sync Summary"),console.log("=".repeat(60)),console.log(`Total files: ${e.totalFileCount}`),console.log(`Successful: ${e.successFileCount}`),console.log(`Skipped: ${e.skippedFileCount}`),console.log(`Failed: ${e.failedFileCount}`),console.log(`Cancelled: ${e.cancelledFileCount}`);for(let r of t)console.log(r);if(console.log("=".repeat(60)),e.failedFiles.length>0){console.log(""),console.log("Failed files:");for(let r of e.failedFiles)console.log(` - ${r.relativePath}: ${r.errorMessage??"Unknown error"}`)}}this.#C({result:this.#w(e),message:t.join(" ")||void 0})}printCheckSummary(e){let t=[...e.missingFiles.map(o=>({name:o.relativePath.split("/").at(-1)??o.relativePath,relativePath:o.relativePath,errorMessage:"Missing on server"})),...e.sizeMismatches.map(o=>({name:o.relativePath.split("/").at(-1)??o.relativePath,relativePath:o.relativePath,errorMessage:`Size mismatch: source ${o.remoteSizeBytes}, server ${o.serverSizeBytes}`})),...e.extraUploadedFiles.map(o=>({name:o.relativePath.split("/").at(-1)??o.relativePath,relativePath:o.relativePath,errorMessage:"Extra uploaded file on server"})),...e.incompleteServerFiles.map(o=>({name:o.relativePath.split("/").at(-1)??o.relativePath,relativePath:o.relativePath,errorMessage:"Incomplete upload on server"}))],r=e.existingCount+e.pathOnlyMatchCount,s={jobId:this.#e.sessionName,status:t.length>0?"failed":"succeeded",successCount:r,skippedCount:0,failedCount:t.length,cancelledCount:0,completedBytes:0,failedFiles:t,completedAt:new Date().toISOString()};this.#C({result:s,stateOverrides:{overall:{filesCompleted:r,filesTotal:e.totalRemoteCount,bytesCompleted:0,bytesTotal:0,bytesRemaining:0,downloadEtaSeconds:0,uploadEtaSeconds:0,totalEtaSeconds:0},counts:{total:e.totalRemoteCount,success:r,failed:t.length,cancelled:0,active:0,queued:0,skipped:0},failedFiles:t}})}#g(){if(!this.isJsonMode||this.#c===null||this.#l===null)return;let e={jobId:this.#e.sessionName,type:"listing",emittedAt:new Date().toISOString(),filesTotal:this.#c,bytesTotal:this.#l,pathRenameWarnings:this.#u,snapshot:this.#b({status:"running",stateOverrides:{overall:{filesCompleted:0,filesTotal:this.#c,bytesCompleted:0,bytesTotal:this.#l,bytesRemaining:this.#l,downloadEtaSeconds:0,uploadEtaSeconds:0,totalEtaSeconds:0}}})};this.#h(e)}#I(e){this.#h({jobId:this.#e.sessionName,type:"progress",emittedAt:new Date().toISOString(),phase:this.#d(),message:e,snapshot:this.#b({status:"running"})})}#P(e){this.#h({jobId:this.#e.sessionName,type:"progress",emittedAt:new Date().toISOString(),phase:this.#d(),message:e,snapshot:this.#b({status:"running"})})}#C({result:e,message:t,stateOverrides:r}){this.isJsonMode&&this.#h({jobId:this.#e.sessionName,type:"summary",emittedAt:e.completedAt,result:e,message:t,snapshot:this.#b({status:e.status,stateOverrides:r})})}#h(e){this.#t(JSON.stringify(e))}#b({status:e,stateOverrides:t}){let r=this.#v(),s=this.#r?{current:this.#r.currentBatch,total:this.#r.totalBatches,filesTotal:this.#r.batchFilesTotal,bytesTotal:this.#r.batchBytesTotal,filesSkipped:this.#r.batchFilesSkipped,bytesSkipped:this.#r.batchBytesSkipped}:void 0,o=this.#r?this.#E({batchState:this.#r,counts:r}):void 0,i=this.#i?{bytesTransferred:this.#i.bytesTransferred,bytesTotal:this.#i.totalBytes,percent:this.#i.percentComplete,speedBps:this.#i.speed,etaSeconds:this.#i.eta}:void 0,a=this.#i?.currentFile?{bytesTransferred:this.#i.currentFile.bytesTransferred,bytesTotal:this.#i.currentFile.totalBytes,percent:this.#i.currentFile.percentComplete,speedBps:this.#i.currentFile.speed,etaSeconds:this.#i.currentFile.eta}:void 0,l={downloadBps:i?.speedBps??0,uploadBps:o?.speedBps??0};return{jobId:this.#e.sessionName,kind:this.#o,status:e,phase:this.#d(),sessionName:this.#e.sessionName,sourceDisplayName:this.#s,aspectProjectId:this.#e.projectId,aspectDirectoryId:this.#e.directoryId,tempDir:this.#e.localTempDir,edgeWorkerUrl:this.#e.edgeWorkerUrl,batch:s,download:i,downloadCurrentFile:a,upload:o,counts:this.#R(r),overall:this.#r?this.#m({batchState:this.#r,counts:r,uploadProgress:o}):void 0,throughput:l,pathRenameWarnings:this.#u,completedBatches:this.#p,failedFiles:[],cancelRequested:!1,discardStagingRequested:!1,updatedAt:new Date().toISOString(),...t}}#E({batchState:e,counts:t}){let r=Math.max(e.batchFilesTotal-e.batchFilesSkipped,0),s=Math.max(e.batchBytesTotal-e.batchBytesSkipped,0),o=s>0?t.uploadedBytes/s*100:0,i=this.#f();return{filesCompleted:t.successFileCount+t.failedFileCount+t.cancelledFileCount,filesTotal:r,bytesUploaded:t.uploadedBytes,bytesTotal:s,percent:o,enqueued:t.totalFileCount,speedBps:i,etaSeconds:this.#T({batchState:e,counts:t,uploadBytesTotal:s,speedBps:i})}}#R(e){return{total:e.totalFileCount,success:e.successFileCount,failed:e.failedFileCount,cancelled:e.cancelledFileCount,active:e.activeFileCount,queued:e.queuedFileCount,skipped:this.#r?.batchFilesSkipped??0}}#m({batchState:e,counts:t,uploadProgress:r}){let s=e.batchFilesSkipped+t.successFileCount+t.failedFileCount+t.cancelledFileCount,o=e.batchBytesSkipped+t.uploadedBytes,i=e.overallFilesCompleted+s,a=e.overallBytesCompleted+o,l=Math.max(e.overallBytesTotal-a,0),c=this.#y(e),u=r?.etaSeconds??0;return{filesCompleted:i,filesTotal:e.overallFilesTotal,bytesCompleted:a,bytesTotal:e.overallBytesTotal,bytesRemaining:l,downloadEtaSeconds:c,uploadEtaSeconds:u,totalEtaSeconds:c+u}}#y(e){let t=e.overallBytesCompleted+e.batchBytesSkipped+(this.#i?.bytesTransferred??0),r=Math.max(e.overallBytesTotal-t,0);if(r===0)return this.#a=0,0;if(this.#i&&this.#i.speed>0){let s=Math.ceil(r/this.#i.speed);return this.#a=s,s}return e.currentPhase==="uploading"||e.currentPhase==="cleaning"||e.currentPhase==="complete"?(this.#a=0,0):this.#a??0}#T({batchState:e,counts:t,uploadBytesTotal:r,speedBps:s}){let o=e.overallBytesCompleted+e.batchBytesSkipped+t.uploadedBytes,i=Math.max(e.overallBytesTotal-o,0);if(i===0)return this.#k=0,0;if(s>0&&r>0){let a=Math.ceil(i/s);return this.#k=a,a}return this.#k??0}#d(){if(!this.#r)return"scanning";if(this.#r.currentPhase==="uploading"){let e=this.#v(),t=Math.max(this.#r.batchFilesTotal-this.#r.batchFilesSkipped,0),r=Math.max(this.#r.batchBytesTotal-this.#r.batchBytesSkipped,0),s=e.successFileCount+e.failedFileCount+e.cancelledFileCount;if(r>0&&e.uploadedBytes>=r&&s<t)return"finalizing"}switch(this.#r.currentPhase){case"downloading":return"downloading";case"scanning":return"scanning";case"syncing_folders":return"syncing_folders";case"uploading":return"uploading";case"cleaning":return"cleaning";case"complete":return"complete";default:return this.#r.currentPhase}}#v(){return this.#n?Object.values(this.#n.uploadAssets).reduce((t,r)=>{switch(t.totalFileCount+=1,t.totalBytes+=r.totalBytesToUpload,t.uploadedBytes+=r.status==="success"?r.totalBytesToUpload:r.bytesUploaded,r.status){case"success":t.successFileCount+=1;break;case"failed":t.failedFileCount+=1;break;case"cancelled":t.cancelledFileCount+=1;break;case"in-progress":t.activeFileCount+=1;break;default:t.queuedFileCount+=1;break}return t},{totalFileCount:0,successFileCount:0,failedFileCount:0,cancelledFileCount:0,activeFileCount:0,queuedFileCount:0,uploadedBytes:0,totalBytes:0}):{totalFileCount:0,successFileCount:0,failedFileCount:0,cancelledFileCount:0,activeFileCount:0,queuedFileCount:0,uploadedBytes:0,totalBytes:0}}#f(){let e=this.#n?.uploadStats.uploadSpeedMbps;return e===void 0||e<=0||!Number.isFinite(e)?0:e*1024*1024/8}#w(e){let t=e.failedFiles.map(s=>({name:s.fileName??s.relativePath.split("/").at(-1)??s.relativePath,relativePath:s.relativePath,errorMessage:s.errorMessage??"Unknown error"})),r=e.cancelledFileCount>0&&e.failedFileCount===0?"cancelled":e.failedFileCount>0?"failed":"succeeded";return{jobId:this.#e.sessionName,status:r,successCount:e.successFileCount,skippedCount:e.skippedFileCount,failedCount:e.failedFileCount,cancelledCount:e.cancelledFileCount,completedBytes:e.completedByteCount??this.#r?.overallBytesCompleted??0,failedFiles:t,completedAt:new Date().toISOString()}}#L(){return this.#e.shard?`${this.#e.shard.index+1}/${this.#e.shard.count} (index ${this.#e.shard.index})`:"disabled"}};function Ts(n){return n.reduce((e,t)=>e+(Number.isFinite(t.size)?t.size:0),0)}var Ve=200,Xe=class{#e;#s;#t;#o;#r;#n;constructor(e,t,r){this.#e=e,this.#s=t??new x({apiUrl:e.apiUrl,apiKey:e.apiKey,edgeWorkerUrl:e.edgeWorkerUrl,sessionId:e.sessionName}),this.#t=new xe({rootDirectoryId:e.directoryId,httpClient:this.#s}),this.#r=r??Y(e.source),this.#n=new Qe({config:e,sourceDisplayName:this.#r.displayName}),this.#o=new Je({config:e,httpClient:this.#s,onSnapshot:s=>this.#n.updateUploadSnapshot(s),analytics:tn})}async run(){try{await this.#i()}finally{await this.#r.shutdown()}}async runBatched(){try{await this.#c()}finally{await this.#r.shutdown()}}async runCheckOnly(){try{await this.#l()}finally{await this.#r.shutdown()}}async#i(){this.#d("Starting data sync..."),await this.#b();let e=this.#C(this.#P(await this.#u()));if(e.length===0){this.#n.log("No files to sync. Exiting."),await this.#E();return}let t={totalFileCount:0,successFileCount:0,skippedFileCount:0,failedFileCount:0,cancelledFileCount:0,completedByteCount:0},r=[],s={batchNumber:1,files:e,totalSize:this.#O(e)};this.#n.startLiveDisplay();try{let i=await this.#h({batch:s,totalBatches:1,overallFilesTotal:e.length,overallBytesTotal:s.totalSize,completedTotals:t,batchDir:this.#e.localTempDir});this.#N(t,r,i,s.totalSize)}finally{this.#n.stopLiveDisplay()}let o={...t,failedFiles:r};this.#f({summary:o}),await this.#R(o),this.#S(o)}async#c(){if(!this.#e.batchSizeBytes)throw new Error("Batch size not configured. Use batchSizeBytes in config.");this.#d("Starting batched data sync...",[`Batch size: ${h(this.#e.batchSizeBytes)}`,`Max concurrent chunks: ${this.#e.maxConcurrent}`]),await this.#b();let e=this.#C(this.#P(await this.#u()));if(e.length===0){this.#n.log("No files to sync. Exiting."),await this.#E();return}let t=Kt(e,this.#e.batchSizeBytes);await this.#T(t);let r={totalFileCount:0,successFileCount:0,skippedFileCount:0,failedFileCount:0,cancelledFileCount:0,completedByteCount:0},s=[],o=this.#O(e);this.#n.startLiveDisplay();try{for(let a of t){let l=await this.#h({batch:a,totalBatches:t.length,overallFilesTotal:e.length,overallBytesTotal:o,completedTotals:r});this.#N(r,s,l,a.totalSize)}}finally{this.#n.stopLiveDisplay()}this.#f({summary:{...r,failedFiles:s},extraLines:[`Batches: ${t.length}`]});let i={...r,failedFiles:s};await this.#R(i),this.#S(i)}async#l(){this.#n.start({kind:"check",title:"Running in check-only mode (no downloads/uploads)...",humanMode:"message"}),await this.#r.prepare(),this.#n.log(`Listing source files from ${this.#r.displayName}...`);let e=await this.#r.listFiles();this.#n.recordSourceListing({files:e,humanDescription:"source files to check",includeHumanTotal:!1});let t=this.#C(this.#P(e));if(t.length===0){this.#n.log("No source files to check. Exiting.");return}this.#n.log("Fetching Aspect project summary...");let r=await this.#p();this.#n.log("Fetching existing Aspect files...");let s=await this.#t.listFilesInSubtree({onProgress:i=>this.#w(i)}),o=this.#a(t,s,r);this.#L(o),this.#n.printCheckSummary(o)}async#u(){this.#n.log("Listing all source files...");let e=await this.#r.listFiles();return this.#n.recordSourceListing({files:e}),e}async#p(){return await this.#s.get(`/projects/${this.#e.projectId}`)}#a(e,t,r){let s=e.map(S=>({relativePath:F(S),sizeBytes:this.#I(S.size)})),o=s.filter(S=>S.sizeBytes===null).length,i=t.filter(S=>S.isUploaded),a=t.filter(S=>S.uploadStateKnown&&!S.isUploaded),l=t.filter(S=>!S.uploadStateKnown).length;l>0&&(this.#n.warn(`Warning: ${l} server asset(s) did not include upload status; treating them as uploaded for check comparison.`),this.#n.blank());let c=this.#k(s),u=this.#g(i),d=new Set([...c.keys(),...u.keys()]),m=0,f=0,p=[],y=[],C=[];for(let S of d){let we=c.get(S)??[],k=u.get(S)??[],E=new Set,ot=[];for(let A of we){if(A.sizeBytes===null){ot.push(A);continue}let $=k.findIndex((v,Ie)=>!E.has(Ie)&&v.sizeBytes===A.sizeBytes);$>=0?(m+=1,E.add($)):ot.push(A)}for(let A of ot){if(A.sizeBytes===null){let v=k.findIndex((Ie,lr)=>!E.has(lr));v>=0?(E.add(v),f+=1):p.push(A);continue}let $=k.findIndex((v,Ie)=>!E.has(Ie));if($>=0){let v=k[$];E.add($),y.push({relativePath:S,remoteSizeBytes:A.sizeBytes,serverSizeBytes:v.sizeBytes,assetId:v.assetId})}else p.push(A)}for(let A=0;A<k.length;A++)E.has(A)||C.push(k[A])}return{totalRemoteCount:e.length,totalServerCount:t.length,projectAssetCount:r.num_assets,projectRootDirectoryId:r.root_directory_id,uploadedServerCount:i.length,unknownUploadStateCount:l,unknownRemoteSizeCount:o,pathOnlyMatchCount:f,existingCount:m,missingFiles:p,sizeMismatches:y,extraUploadedFiles:C,incompleteServerFiles:a}}#k(e){let t=new Map;for(let r of e){let s=b(r.relativePath),o=t.get(s)??[];o.push({...r,relativePath:s}),t.set(s,o)}return t}#g(e){let t=new Map;for(let r of e){let s=b(r.relativePath),o=t.get(s)??[];o.push({...r,relativePath:s}),t.set(s,o)}return t}#I(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:null}#P(e){let t=Ue(e);return t.changes.length===0||this.#n.recordPathRenameWarnings({count:t.changes.length,sample:t.changes.slice(0,10).map(r=>({sourcePath:r.sourcePath,targetPath:r.targetPath}))}),t.files}#C(e){let t=An(e,this.#e.shard);return this.#e.shard&&(this.#n.log(`Shard ${this.#e.shard.index+1}/${this.#e.shard.count}: ${t.length} of ${e.length} planned file(s)`),this.#n.log(`Shard size: ${h(this.#O(t))}`),this.#n.blank()),t}async#h(e){let t=e.batchDir??Lt.join(this.#e.localTempDir,`batch${e.batch.batchNumber}`);await ge.mkdir(t,{recursive:!0});let r=e.batch.files.map(d=>this.#r.resolveLocalFile(d,t));this.#n.updateBatchState({currentBatch:e.batch.batchNumber,totalBatches:e.totalBatches,batchFilesTotal:r.length,batchBytesTotal:e.batch.totalSize,batchFilesSkipped:0,batchBytesSkipped:0,overallFilesCompleted:e.completedTotals.successFileCount+e.completedTotals.skippedFileCount,overallFilesTotal:e.overallFilesTotal,overallBytesCompleted:this.#U(e.completedTotals,e.overallBytesTotal),overallBytesTotal:e.overallBytesTotal,currentPhase:"scanning",extraDetails:`Preparing ${r.length} files...`}),this.#n.updateBatchState({currentBatch:e.batch.batchNumber,totalBatches:e.totalBatches,batchFilesTotal:r.length,batchBytesTotal:e.batch.totalSize,batchFilesSkipped:0,batchBytesSkipped:0,overallFilesCompleted:e.completedTotals.successFileCount+e.completedTotals.skippedFileCount,overallFilesTotal:e.overallFilesTotal,overallBytesCompleted:this.#U(e.completedTotals,e.overallBytesTotal),overallBytesTotal:e.overallBytesTotal,currentPhase:"syncing_folders",extraDetails:"Ensuring target directories exist..."});let s=await this.#t.ensureDirectories(r);this.#n.updateBatchState({currentBatch:e.batch.batchNumber,totalBatches:e.totalBatches,batchFilesTotal:r.length,batchBytesTotal:e.batch.totalSize,batchFilesSkipped:0,batchBytesSkipped:0,overallFilesCompleted:e.completedTotals.successFileCount+e.completedTotals.skippedFileCount,overallFilesTotal:e.overallFilesTotal,overallBytesCompleted:this.#U(e.completedTotals,e.overallBytesTotal),overallBytesTotal:e.overallBytesTotal,currentPhase:"scanning",extraDetails:"Checking existing assets..."});let o=await this.#m(s),i=this.#y(o),a=e.batch.files.filter((d,m)=>o[m]?.preSkipped!==!0),l=Lt.join(this.#e.localTempDir,`batch${e.batch.batchNumber}.txt`),c=async()=>{await qt(l),this.#e.keepLocal||await ge.rm(t,{recursive:!0,force:!0}),this.#n.resetUploadSnapshot()};if(a.length===0){let d={totalFileCount:o.length,successFileCount:0,skippedFileCount:o.length,failedFileCount:0,cancelledFileCount:0,failedFiles:[]};return this.#n.updateBatchState({currentBatch:e.batch.batchNumber,totalBatches:e.totalBatches,batchFilesTotal:r.length,batchBytesTotal:e.batch.totalSize,batchFilesSkipped:i.skippedFileCount,batchBytesSkipped:i.skippedByteCount,overallFilesCompleted:e.completedTotals.successFileCount+e.completedTotals.skippedFileCount+d.skippedFileCount,overallFilesTotal:e.overallFilesTotal,overallBytesCompleted:this.#U(e.completedTotals,e.overallBytesTotal)+e.batch.totalSize,overallBytesTotal:e.overallBytesTotal,currentPhase:"complete",extraDetails:"everything already synced"}),this.#n.persistCurrentBatchLine(),await c(),d}this.#n.updateBatchState({currentBatch:e.batch.batchNumber,totalBatches:e.totalBatches,batchFilesTotal:r.length,batchBytesTotal:e.batch.totalSize,batchFilesSkipped:i.skippedFileCount,batchBytesSkipped:i.skippedByteCount,overallFilesCompleted:e.completedTotals.successFileCount+e.completedTotals.skippedFileCount,overallFilesTotal:e.overallFilesTotal,overallBytesCompleted:this.#U(e.completedTotals,e.overallBytesTotal),overallBytesTotal:e.overallBytesTotal,currentPhase:"downloading"}),await this.#r.materializeBatch({files:a,batchDir:t,batchFilePath:l,onProgress:d=>this.#n.updateDownloadProgress(d)}),this.#n.updateBatchState({currentBatch:e.batch.batchNumber,totalBatches:e.totalBatches,batchFilesTotal:r.length,batchBytesTotal:e.batch.totalSize,batchFilesSkipped:i.skippedFileCount,batchBytesSkipped:i.skippedByteCount,overallFilesCompleted:e.completedTotals.successFileCount+e.completedTotals.skippedFileCount,overallFilesTotal:e.overallFilesTotal,overallBytesCompleted:this.#U(e.completedTotals,e.overallBytesTotal),overallBytesTotal:e.overallBytesTotal,currentPhase:"uploading"});let u=await this.#o.uploadFiles(o);return this.#A(u)?(this.#n.updateBatchState({currentBatch:e.batch.batchNumber,totalBatches:e.totalBatches,batchFilesTotal:r.length,batchBytesTotal:e.batch.totalSize,batchFilesSkipped:i.skippedFileCount,batchBytesSkipped:i.skippedByteCount,overallFilesCompleted:e.completedTotals.successFileCount+e.completedTotals.skippedFileCount+u.successFileCount+u.skippedFileCount,overallFilesTotal:e.overallFilesTotal,overallBytesCompleted:this.#U(e.completedTotals,e.overallBytesTotal)+e.batch.totalSize,overallBytesTotal:e.overallBytesTotal,currentPhase:"complete",extraDetails:"failed; local files preserved"}),this.#n.persistCurrentBatchLine(),u):(this.#n.updateBatchState({currentBatch:e.batch.batchNumber,totalBatches:e.totalBatches,batchFilesTotal:r.length,batchBytesTotal:e.batch.totalSize,batchFilesSkipped:i.skippedFileCount,batchBytesSkipped:i.skippedByteCount,overallFilesCompleted:e.completedTotals.successFileCount+e.completedTotals.skippedFileCount+u.successFileCount+u.skippedFileCount,overallFilesTotal:e.overallFilesTotal,overallBytesCompleted:this.#U(e.completedTotals,e.overallBytesTotal)+e.batch.totalSize,overallBytesTotal:e.overallBytesTotal,currentPhase:"cleaning"}),await c(),this.#n.updateBatchState({currentBatch:e.batch.batchNumber,totalBatches:e.totalBatches,batchFilesTotal:r.length,batchBytesTotal:e.batch.totalSize,batchFilesSkipped:i.skippedFileCount,batchBytesSkipped:i.skippedByteCount,overallFilesCompleted:e.completedTotals.successFileCount+e.completedTotals.skippedFileCount+u.successFileCount+u.skippedFileCount,overallFilesTotal:e.overallFilesTotal,overallBytesCompleted:this.#U(e.completedTotals,e.overallBytesTotal)+e.batch.totalSize,overallBytesTotal:e.overallBytesTotal,currentPhase:"complete"}),this.#n.persistCurrentBatchLine(),u)}async#b(){this.#n.log("Preparing source..."),await this.#r.prepare(),this.#n.log("Source ready"),this.#n.blank(),this.#n.log("Creating session directory..."),await ge.mkdir(this.#e.localTempDir,{recursive:!0}),this.#n.log(`Session directory: ${this.#e.localTempDir}`),this.#n.blank()}async#E(){this.#e.keepLocal||(this.#n.blank(),this.#n.log("Cleaning up session directory..."),await ge.rm(this.#e.localTempDir,{recursive:!0,force:!0}),this.#n.log(`Deleted session directory: ${this.#e.localTempDir}`))}async#R(e){if(this.#A(e)){this.#n.blank(),this.#n.log(`Preserving session directory for retry/debugging: ${this.#e.localTempDir}`);return}await this.#E()}async#m(e){let t=await this.#t.checkAssetsExistence(e.map(r=>({directory_id:r.directoryId,name:r.file.fileName,size_bytes:r.file.size})));return e.map((r,s)=>({file:r.file,directoryId:r.directoryId,preSkipped:t[s]?.exists===!0}))}#y(e){return e.reduce((t,r)=>(r.preSkipped===!0&&(t.skippedFileCount+=1,t.skippedByteCount+=r.file.size),t),{skippedFileCount:0,skippedByteCount:0})}async#T(e){this.#n.log("Creating batches..."),this.#n.log(`Created ${e.length} batches`);let t=[];for(let r of e){let s=`Batch ${r.batchNumber}: ${r.files.length} files, ${h(r.totalSize)}`;t.push(s),this.#n.log(s)}await ge.writeFile(Lt.join(this.#e.localTempDir,"batches.txt"),`${t.join(`
|
|
18
20
|
`)}
|
|
19
|
-
`,"utf-8"),
|
|
20
|
-
`,{encoding:"utf-8",mode:
|
|
21
|
+
`,"utf-8"),this.#n.blank()}#d(e,t=[]){this.#n.start({kind:"sync",title:e,extraLines:t})}#v(){return this.#e.shard?`${this.#e.shard.index+1}/${this.#e.shard.count} (index ${this.#e.shard.index})`:"disabled"}#f(e){this.#n.printSummary({summary:e.summary,extraLines:e.extraLines})}#w(e){this.#n.log(`Aspect scan: ${e.scannedDirectoryCount}/${e.queuedDirectoryCount} directories, ${e.fileCount} files found`)}#L(e){if(this.#n.isJsonMode)return;let t=e.missingFiles.length+e.sizeMismatches.length+e.extraUploadedFiles.length+e.incompleteServerFiles.length;console.log(""),console.log("=".repeat(60)),console.log("Check Summary"),console.log("=".repeat(60)),console.log(`Total (remote): ${e.totalRemoteCount}`),console.log(`Total (server): ${e.totalServerCount}`),console.log(`Project asset count: ${e.projectAssetCount}`),console.log(`Project count vs scanned server: ${e.projectAssetCount-e.totalServerCount}`),console.log(`Uploaded (server): ${e.uploadedServerCount}`),console.log(`Upload status unknown: ${e.unknownUploadStateCount}`),console.log(`Exact matches: ${e.existingCount}`),console.log(`Path-only matches (unknown remote size): ${e.pathOnlyMatchCount}`),console.log(`Remote sizes unknown: ${e.unknownRemoteSizeCount}`),console.log(`Missing on server: ${e.missingFiles.length}`),console.log(`Size mismatches: ${e.sizeMismatches.length}`),console.log(`Extra on server: ${e.extraUploadedFiles.length}`),console.log(`Incomplete uploads on server: ${e.incompleteServerFiles.length}`),console.log(`Total mismatches: ${t}`),console.log("=".repeat(60)),e.projectRootDirectoryId!==this.#e.directoryId?(console.log(""),console.log(`Warning: --asp-directory-id (${this.#e.directoryId}) is not the project root directory (${e.projectRootDirectoryId}), so --check is comparing only that directory subtree.`)):e.projectAssetCount!==e.totalServerCount&&(console.log(""),console.log("Warning: project asset count differs from the live filesystem subtree scan. The project card uses cached project stats; the subtree scan is what --check compared against Drive.")),this.#B("Files missing on server:",e.missingFiles),this.#D(e.sizeMismatches),this.#M("Extra files on server:",e.extraUploadedFiles),this.#M("Incomplete uploads on server:",e.incompleteServerFiles)}#B(e,t){if(t.length!==0){console.log(""),console.log(e);for(let r of t.slice(0,Ve))console.log(` - ${r.relativePath} (${this.#_(r.sizeBytes)})`);this.#x(t.length)}}#D(e){if(e.length!==0){console.log(""),console.log("Files with size mismatches:");for(let t of e.slice(0,Ve))console.log(` - ${t.relativePath} (remote ${h(t.remoteSizeBytes)}, server ${h(t.serverSizeBytes)}, asset ${t.assetId})`);this.#x(e.length)}}#M(e,t){if(t.length!==0){console.log(""),console.log(e);for(let r of t.slice(0,Ve))console.log(` - ${r.relativePath} (${h(r.sizeBytes)}, asset ${r.assetId})`);this.#x(t.length)}}#x(e){let t=e-Ve;t>0&&console.log(` ...and ${t} more`)}#_(e){return e===null?"unknown remote size":h(e)}#N(e,t,r,s){e.totalFileCount+=r.totalFileCount,e.successFileCount+=r.successFileCount,e.skippedFileCount+=r.skippedFileCount,e.failedFileCount+=r.failedFileCount,e.cancelledFileCount+=r.cancelledFileCount,e.completedByteCount+=s,t.push(...r.failedFiles)}#S(e){let t=e.failedFileCount+e.cancelledFileCount;if(t>0)throw new Error(`Sync completed with ${t} unsuccessful upload(s)`)}#A(e){return e.failedFileCount+e.cancelledFileCount>0}#O(e){return e.reduce((t,r)=>t+r.size,0)}#U(e,t){return Math.min(e.completedByteCount,t)}};import ks from"node:fs";import{chmod as wn,mkdir as vs,writeFile as Us}from"node:fs/promises";import{stdin as _,stdout as Ze}from"node:process";import Ls from"node:os";import Tn from"node:path";var In=448,Pn=384,xs="https://api.aspect.inc";function xt(){return Tn.join(Ls.homedir(),".config","aspect-sync","aspect-auth.json")}function Ds(n=xt()){let e;try{e=ks.readFileSync(n,"utf-8")}catch(r){throw r.code==="ENOENT"?Bs(n):r}let t;try{t=JSON.parse(e)}catch(r){throw new Error(`Aspect auth file ${n} is not valid JSON: ${r.message}`)}return Un({authFilePath:n,value:t})}function kn(n=xt()){try{return Ds(n)}catch(e){if(e.code==="ENOENT")return null;throw e}}async function _s(n,e){Un({authFilePath:n,value:e});let t=Tn.dirname(n);await vs(t,{recursive:!0,mode:In}),await wn(t,In),await Us(n,`${JSON.stringify(e,null,2)}
|
|
22
|
+
`,{encoding:"utf-8",mode:Pn}),await wn(n,Pn)}async function vn(n,e={}){let t=e.prompts??{promptPassword:zs},s=(n.aspApiKey??await t.promptPassword("Aspect API key: ")).trim();if(!s)throw new Error("--asp-api-key or API key prompt cannot be empty");let o=n.aspApiUrl??xs;await(e.validateApiKey??Os)({apiUrl:o,apiKey:s});let i={apiKey:s};n.aspApiUrl&&(i.apiUrl=n.aspApiUrl),n.aspEdgeWorkerUrl&&(i.edgeWorkerUrl=n.aspEdgeWorkerUrl);let a=n.authFile??xt();await _s(a,i),console.log(`Saved Aspect auth to ${a}`)}async function Os(n){let e=await fetch(new URL("/users/me",n.apiUrl),{headers:{Authorization:`Bearer ${n.apiKey}`}});if(e.ok)return;let t=await e.text();throw new Error(`Aspect API key validation failed: ${e.status} ${e.statusText}${t?` ${t}`:""}`)}function Bs(n){let e=new Error(`Error: Aspect API key not found; pass --asp-api-key, set ASPECT_API_KEY, or run aspect-sync login to create ${n}`);return e.code="ENOENT",e}function Un(n){if(!Ms(n.value))throw new Error(`Aspect auth file ${n.authFilePath} must contain a non-empty apiKey string`);return n.value}function Ms(n){if(!n||typeof n!="object")return!1;let e=n;return Ns(e.apiKey)&&Rn(e.apiUrl)&&Rn(e.edgeWorkerUrl)}function Ns(n){return typeof n=="string"&&n.length>0}function Rn(n){return n===void 0||typeof n=="string"}function zs(n){if(!_.isTTY||!Ze.isTTY)throw new Error("Interactive Aspect API key prompt requires a TTY; provide --asp-api-key");return new Promise((e,t)=>{let r=[],s=_.isRaw,o=()=>{_.off("data",i),_.setRawMode(s),_.pause()},i=a=>{let l=a.toString("utf-8");for(let c of l){if(c===""){o(),Ze.write(`
|
|
23
|
+
`),t(new Error("Aspect API key prompt cancelled"));return}if(c==="\r"||c===`
|
|
24
|
+
`){o(),Ze.write(`
|
|
25
|
+
`),e(r.join(""));return}if(c==="\x7F"){r.pop();continue}c>=" "&&r.push(c)}};Ze.write(n),_.setRawMode(!0),_.resume(),_.on("data",i)})}import{createInterface as bo}from"node:readline/promises";import{stdin as Ao,stdout as Fo}from"node:process";import Ks from"node:fs";import qs from"node:os";import Se from"node:path";import _n from"node:fs";import{chmod as Ln,mkdir as Gs,writeFile as $s}from"node:fs/promises";import js from"node:os";import On from"node:path";var xn=448,Dn=384;function ye(){return On.join(js.homedir(),".config","aspect-sync","lucidlink-auth.json")}function Bn(n=ye()){let e;try{e=_n.readFileSync(n,"utf-8")}catch(r){throw r.code==="ENOENT"?Hs(n):r}let t;try{t=JSON.parse(e)}catch(r){throw new Error(`LucidLink auth file ${n} is not valid JSON: ${r.message}`)}return zn({authFilePath:n,value:t})}async function Mn(n,e){zn({authFilePath:n,value:e});let t=On.dirname(n);await Gs(t,{recursive:!0,mode:xn}),await Ln(t,xn),await $s(n,`${JSON.stringify(e,null,2)}
|
|
26
|
+
`,{encoding:"utf-8",mode:Dn}),await Ln(n,Dn)}function Nn(n){let e=_n.readFileSync(n,"utf-8").replace(/\r?\n$/,"");if(e.length===0)throw new Error(`Error: LucidLink password file is empty: ${n}`);return e}function Hs(n){let e=new Error(`Error: LucidLink auth file not found at ${n}; run aspect-sync lucidlink login before syncing`);return e.code="ENOENT",e}function zn(n){if(!Ws(n.value))throw new Error(`LucidLink auth file ${n.authFilePath} must contain non-empty filespace, user, and password strings`);return n.value}function Ws(n){if(!n||typeof n!="object")return!1;let e=n;return Dt(e.filespace)&&Dt(e.user)&&Dt(e.password)}function Dt(n){return typeof n=="string"&&n.length>0}var Js="phc_rDzmwduU3NzHyELgLEg7nMjqpTgaSpC2a6tMKL8VyjN",Ys="https://t.aspect.inc",Qs="https://t.aspect.inc";function _t(n){let e=n.match(/^(\d+(?:\.\d+)?)\s*(B|KB|MB|GB|TB)$/i);if(!e)return null;let t=parseFloat(e[1]),r=e[2].toUpperCase(),s={B:1,KB:1e3,MB:1e3*1e3,GB:1e3*1e3*1e3,TB:1e3*1e3*1e3*1e3};return t*(s[r]||1)}function $n(n){return et({options:n.options,environment:n.environment,now:n.now,highResolutionTime:n.highResolutionTime,buildSourceConfig:()=>Ce(n.options)})}function jn(n){return et({options:n.options,environment:n.environment,now:n.now,highResolutionTime:n.highResolutionTime,buildSourceConfig:()=>Zs(n.options)})}function Hn(n){return et({options:n.options,environment:n.environment,now:n.now,highResolutionTime:n.highResolutionTime,buildSourceConfig:e=>be({options:n.options,localTempDir:e.localTempDir})})}function Wn(n){return et({options:n.options,environment:n.environment,now:n.now,highResolutionTime:n.highResolutionTime,buildSourceConfig:()=>Ae({options:n.options})})}function et(n){let e=Q({value:n.options.aspDirectoryId,optionName:"--asp-directory-id"}),t=Q({value:n.options.aspProjectId,optionName:"--asp-project-id"}),r=Xs({options:n.options,environment:n.environment})?kn():null,s=n.options.aspApiKey||n.environment.ASPECT_API_KEY||r?.apiKey||"";if(!s)throw new Error("Error: --asp-api-key is required (or set ASPECT_API_KEY env variable or run aspect-sync login)");let o=G({value:n.options.uploadConcurrent,optionName:"--upload-concurrent"}),i=so(n.options.batchSize),a=oo({shardCount:n.options.shardCount,shardIndex:n.options.shardIndex}),l=n.options.session??io({now:n.now??new Date,highResolutionTime:n.highResolutionTime??process.hrtime.bigint()}),c=n.options.tempDir||Se.join(qs.homedir(),".aspect","sync"),u=Se.join(c,l);return{source:n.buildSourceConfig({localTempDir:u}),directoryId:e,projectId:t,apiUrl:n.options.aspApiUrl||n.environment.ASPECT_API_URL||r?.apiUrl||"https://api.aspect.inc",edgeWorkerUrl:n.options.aspEdgeWorkerUrl||n.environment.ASPECT_EDGE_WORKER_URL||r?.edgeWorkerUrl||"https://mackinac.aspect.inc",apiKey:s,maxConcurrent:o,keepLocal:n.options.keepLocal,localTempDir:u,sessionName:l,batchSizeBytes:i,shard:a,progressMode:Vs(n.options.progress),analytics:{posthogKey:n.environment.ASPECT_POSTHOG_KEY||n.environment.POSTHOG_KEY||n.environment.POSTHOG_API_KEY||Js,posthogHost:n.environment.ASPECT_POSTHOG_HOST||n.environment.POSTHOG_HOST||Ys||Qs,disabled:Gn(n.environment.ASPECT_DISABLE_POSTHOG)||Gn(n.environment.POSTHOG_DISABLED)}}}function Vs(n){if(n===void 0)return"human";if(n==="human"||n==="json")return n;throw new Error("--progress must be either human or json")}function Xs(n){if(!!!(n.options.aspApiKey||n.environment.ASPECT_API_KEY))return!0;let t=!!(n.options.aspApiUrl||n.environment.ASPECT_API_URL),r=!!(n.options.aspEdgeWorkerUrl||n.environment.ASPECT_EDGE_WORKER_URL);return!t||!r}function Ce(n){let e=Q({value:n.sourcePath,optionName:"--source-path"});if(!n.remote)throw new Error("Error: --remote is required for rclone");let t=G({value:n.rcloneTransfers??"4",optionName:"--rclone-transfers"}),r=G({value:n.rcloneMultiThreadStreams??"4",optionName:"--rclone-multi-thread-streams"});return{kind:"rclone",remote:n.remote,remotePath:e,rcloneOptions:{transfers:t,checkers:t>=16?Math.floor(t/4):t,multiThreadStreams:r,multiThreadChunkSize:n.rcloneMultiThreadChunkSize??"64MiB",multiThreadCutoff:n.rcloneMultiThreadCutoff??"64MiB",bufferSize:n.rcloneBufferSize??"64M",useMmap:n.rcloneNoMmap!==!0,extraRcloneArgs:n.rcloneExtra??[]}}}function Zs(n){let e=Q({value:n.sourcePath,optionName:"--source-path"});return{kind:"local",rootPath:Se.resolve(e)}}function be(n){let e=Q({value:n.options.sourcePath,optionName:"--source-path"}),t=ye(),r=Bn(t),s=G({value:n.options.lucidInstance??"9001",optionName:"--lucid-instance"}),o=`${n.localTempDir}-lucid`;return{kind:"lucidlink",filespace:r.filespace,user:r.user,password:r.password,filespacePath:no(e),instanceId:s,workDir:o,mountPoint:Se.join(o,"mnt"),cacheRootPath:Se.join(o,"cache"),cacheSize:n.options.lucidCacheSize}}function Ae(n){let e=Q({value:n.options.sourceFolderId,optionName:"--source-folder-id"}),t=J(),r=eo(t);return{kind:"frameio",accountId:r,folderId:e,downloadConcurrency:G({value:n.options.frameioDownloadConcurrent??"4",optionName:"--frameio-download-concurrent"}),pageSize:G({value:n.options.frameioPageSize??"100",optionName:"--frameio-page-size"})}}function Q(n){if(!n.value)throw new Error(`Error: ${n.optionName} is required`);return n.value}function eo(n){let e;try{e=Ks.readFileSync(n,"utf-8")}catch(r){throw r.code==="ENOENT"?new Error(`Error: Frame.io auth file not found at ${n}; run aspect-sync frameio login before syncing`):r}let t=JSON.parse(e);if(!to(t))throw new Error(`Error: Frame.io sync requires a default account ID in ${n}; run aspect-sync frameio login to select a default account, or add defaultAccountId to the auth file.`);return t.defaultAccountId}function to(n){if(!n||typeof n!="object")return!1;let e=n;return typeof e.defaultAccountId=="string"&&e.defaultAccountId.length>0}function no(n){let e=n.replace(/^\/+/,"").replace(/\/+$/,"");if(e.split("/").some(t=>t===".."))throw new Error(`Error: --source-path cannot contain parent directory segments: ${n}`);return e}function G(n){let e=parseInt(n.value,10);if(Number.isNaN(e)||e<1)throw new Error(`Error: ${n.optionName} must be a positive integer`);return e}function ro(n){let e=parseInt(n.value,10);if(Number.isNaN(e)||e<0)throw new Error(`Error: ${n.optionName} must be a non-negative integer`);return e}function so(n){if(!n)return;let e=_t(n);if(e===null)throw new Error(`Error: Invalid batch size format: ${n}`);return e}function oo(n){if(!n.shardCount&&!n.shardIndex)return;if(!n.shardCount||!n.shardIndex)throw new Error("Error: --shard-count and --shard-index must be provided together");let e=G({value:n.shardCount,optionName:"--shard-count"}),t=ro({value:n.shardIndex,optionName:"--shard-index"});if(t>=e)throw new Error("Error: --shard-index must be less than --shard-count");return{count:e,index:t}}function Gn(n){return n?["1","true","yes"].includes(n.toLowerCase()):!1}function io(n){let e=n.now.getFullYear(),t=String(n.now.getMonth()+1).padStart(2,"0"),r=String(n.now.getDate()).padStart(2,"0"),s=String(n.now.getHours()).padStart(2,"0"),o=String(n.now.getMinutes()).padStart(2,"0"),i=String(n.now.getSeconds()).padStart(2,"0"),a=n.highResolutionTime%1000000000n,l=String(a).padStart(9,"0");return`${e}-${t}-${r}_${s}h-${o}m-${i}s-${l}ns`}import{createReadStream as ao}from"node:fs";import{mkdir as Ot,rm as Bt,writeFile as lo}from"node:fs/promises";import co from"node:os";import Fe from"node:path";var uo=20;function I(n){let e=n.session??Co(n.commandName),t=n.tempDir??Fe.join(co.homedir(),".aspect","sync");return{sessionName:e,localTempDir:Fe.join(t,e)}}function R(n,e){let t=parseInt(n,10);if(Number.isNaN(t)||t<1)throw new Error(`${e} must be a positive integer`);return t}function V(n,e){if(!n)return;let t=_t(n);if(t===null)throw new Error(`${e} must be a size like 500MB, 10GB, or 1TB`);return t}async function X(n){let e=Y(n.sourceConfig);try{console.log(`Doctor: ${e.displayName}`),await Kn(n.localTempDir),console.log(`Writable temp path: ${n.localTempDir}`);for(let r of yo(n.sourceConfig))await Kn(r),console.log(`Writable cache path: ${r}`);for(let r of n.tuningWarnings??[])console.warn(`Warning: ${r}`);await e.prepare(),console.log("Source prepared");let t=await Mt(e);qn(t.changes),console.log(`Source root access: OK (${t.files.length} files, ${h(tt(t.files))})`),console.log("Doctor checks passed")}finally{try{await Bt(n.localTempDir,{recursive:!0,force:!0})}finally{await e.shutdown()}}}async function Z(n){let e=Y(n.sourceConfig);try{await e.prepare();let t=await Mt(e);qn(t.changes),po({source:e,files:t.files,sampleSize:n.sampleSize??uo})}finally{await e.shutdown()}}async function ee(n){let e=Y(n.sourceConfig);try{await e.prepare();let t=await Mt(e),r=go({files:t.files,maxFiles:n.maxFiles,maxBytes:n.maxBytes});if(r.length===0)throw new Error("No source files available to probe");console.log(`Probe source: ${e.displayName}`),console.log(`Probe files: ${r.length}`),console.log(`Probe size: ${h(tt(r))}`);let s=Date.now(),o=await mo({source:e,sourceConfig:n.sourceConfig,files:r,localTempDir:n.localTempDir}),i=Math.max((Date.now()-s)/1e3,.001);console.log(`Probe complete: ${h(o)} in ${i.toFixed(2)}s (${Ye(o/i)})`)}finally{try{n.keepLocal!==!0&&await Bt(n.localTempDir,{recursive:!0,force:!0})}finally{await e.shutdown()}}}async function Mt(n){console.log(`Listing source files from ${n.displayName}...`);let e=await n.listFiles();return Ue(e)}function po(n){console.log(`Source: ${n.source.displayName}`),console.log(`Files: ${n.files.length}`),console.log(`Total size: ${h(tt(n.files))}`);let e=n.files.slice(0,n.sampleSize);if(e.length===0)return;console.log("Sample paths:");for(let r of e)console.log(`- ${So(r)} (${h(r.size)})`);let t=n.files.length-e.length;t>0&&console.log(`...and ${t} more`)}function qn(n){if(n.length===0)return;let e=n.slice(0,10).map(s=>`${s.sourcePath} -> ${s.targetPath}`).join(`
|
|
21
27
|
`),t=n.length-10,r=t>0?`
|
|
22
28
|
...and ${t} more renamed target path(s)`:"";console.warn(`Warning: ${n.length} remote file path(s) were renamed for Aspect compatibility.
|
|
23
29
|
${e}${r}
|
|
24
|
-
`)}async function Ts(n){await Rt(n.localTempDir,{recursive:!0});let e=ge.join(n.localTempDir,"probe"),t=ge.join(n.localTempDir,"probe-files.txt");if(vs(n.sourceConfig))return await Rt(e,{recursive:!0}),await n.source.materializeBatch({files:n.files,batchDir:e,batchFilePath:t}),Ye(n.files);let r=0;for(let s of n.files){let i=n.source.resolveLocalFile(s,e);r+=await Ls(i.absolutePath)}return r}function vs(n){switch(n.kind){case"rclone":case"frameio":return!0;case"local":case"lucidlink":return!1;default:{let e=n;throw new Error(`Unsupported source kind: ${JSON.stringify(e)}`)}}}async function Ls(n){return await new Promise((e,t)=>{let r=Es(n),s=0;r.on("data",i=>{s+=Buffer.isBuffer(i)?i.length:Buffer.byteLength(i)}),r.on("error",t),r.on("end",()=>e(s))})}function xs(n){let e=[],t=0;for(let r of n.files){if(e.length>=n.maxFiles||n.maxBytes!==void 0&&e.length>0&&t+r.size>n.maxBytes)break;e.push(r),t+=r.size}return e}async function En(n){await Rt(n,{recursive:!0});let e=ge.join(n,`.aspect-sync-write-test-${process.pid}-${Date.now()}`);await Is(e,"","utf-8"),await Pt(e,{force:!0})}function Us(n){return n.kind!=="lucidlink"?[]:[n.cacheRootPath]}function Ds(n){let e=w(n);return e===n.path?e:`${n.path} -> ${e}`}function Ye(n){return n.reduce((e,t)=>e+t.size,0)}function _s(n){let e=new Date().toISOString().replace(/[:.]/g,"-");return`${n}-${e}`}function kn(n){let e=n.command("frameio").description("Frame.io auth, discovery, and bandwidth diagnostics");e.command("login").description("Authenticate to Frame.io V4 via Adobe OAuth PKCE and store refresh credentials").option("--client-id <id>","Adobe OAuth client ID",tn()).action(async s=>{await Ns(s)}),e.command("accounts").description("List Frame.io accounts accessible to the current token").action(async s=>{let o=await(await Ve(s)).listAccounts();Qe(o)}),e.command("workspaces").description("List workspaces in the login-selected Frame.io account").action(async s=>{let i=await Ve(s),o=await vt(s),a=await i.listWorkspaces(o);Qe(a)}),e.command("projects").description("List Frame.io projects in the login-selected account").option("--workspace-id <id>","Optionally scope projects to a Frame.io workspace ID").option("--page-size <number>","Frame.io page size","100").action(async s=>{let i=await Ve(s),o=await vt(s),a=Pn(s.pageSize,"--page-size"),l=s.workspaceId?await i.listProjects({accountId:o,workspaceId:s.workspaceId,pageSize:a}):await i.listAccountProjects({accountId:o,pageSize:a});Qe(l)}),e.command("folders").description("List children in a Frame.io folder in the login-selected account").requiredOption("--folder-id <id>","Frame.io folder ID").option("--page-size <number>","Frame.io page size","100").action(async s=>{let i=await Ve(s),o=await vt(s),a=await i.listFolderChildren({accountId:o,folderId:s.folderId,pageSize:Pn(s.pageSize,"--page-size")});Qe(a)});let t=Tt(e.command("doctor").description("Check Frame.io auth, account, and source folder access"));Rn(t).action(async s=>{let i=R({tempDir:s.tempDir,session:s.session,commandName:"frameio-doctor"});await V({sourceConfig:fe({options:s}),localTempDir:i.localTempDir})}),Tt(e.command("list").description("List planned Frame.io source files before syncing")).option("--sample-size <number>","Number of planned paths to print","20").action(async s=>{await Q({sourceConfig:fe({options:s}),sampleSize:P(s.sampleSize,"--sample-size")})});let r=Tt(e.command("probe").description("Measure Frame.io original download throughput without uploading to Aspect")).option("--max-files <number>","Maximum files to download for the probe","1").option("--max-bytes <size>","Soft maximum bytes to download for the probe").option("--keep-local","Keep downloaded probe files in the temp directory",!1);Rn(r).action(async s=>{let i=R({tempDir:s.tempDir,session:s.session,commandName:"frameio-probe"});await J({sourceConfig:fe({options:s}),localTempDir:i.localTempDir,maxFiles:P(s.maxFiles,"--max-files"),maxBytes:Y(s.maxBytes,"--max-bytes"),keepLocal:s.keepLocal})})}function Tt(n){return n.requiredOption("--source-folder-id <id>","Frame.io folder ID to use as the source root").option("--frameio-download-concurrent <number>","Concurrent Frame.io original downloads","4").option("--frameio-page-size <number>","Frame.io folder listing page size","100")}function Rn(n){return n.option("--temp-dir <path>","Local temporary directory for helper downloads and checks").option("--session <name>","Session name for helper temp paths")}async function Ns(n){let e=nn(),t=rn({clientId:n.clientId,codeChallenge:e.challenge});console.log("Open this URL in a browser and approve access:"),console.log(t),console.log("");let r=await Tn("Paste the full redirected URL or code: "),s=sn(r),i=await on({clientId:n.clientId,code:s,codeVerifier:e.verifier}),a=await new B({token:i.access_token}).listAccounts(),l=await zs({accounts:a}),c=W();await bt(c,At({clientId:n.clientId,token:i,defaultAccountId:l})),console.log(`Saved Frame.io auth to ${c}`)}async function Ve(n){let e=await Ne();return new B({token:e})}async function vt(n){let e=W(),t=await Ct(e);if(t.defaultAccountId)return t.defaultAccountId;throw new Error("Frame.io default account ID is missing; run aspect-sync frameio login.")}async function zs(n){if(n.accounts.length===0)throw new Error("Frame.io login did not return any accessible accounts");let e=n.writeOutput??(r=>console.log(r));if(n.accounts.length===1){let r=n.accounts[0];return e(`Selected default Frame.io account: ${Lt(r)}`),r.id}let t=n.promptForInput??Tn;for(e("Select the default Frame.io account for sync:"),n.accounts.forEach((r,s)=>{e(`${s+1}. ${Lt(r)}`)});;){let r=(await t("Account number or ID: ")).trim(),s=$s(n.accounts,r);if(s)return e(`Selected default Frame.io account: ${Lt(s)}`),s.id;e("Invalid account selection. Enter a listed number or account ID.")}}async function Tn(n){let e=Os({input:Bs,output:Ms});try{return await e.question(n)}finally{e.close()}}function $s(n,e){let t=Number.parseInt(e,10);return String(t)===e&&t>=1&&t<=n.length?n[t-1]:n.find(r=>r.id===e)}function Lt(n){let e=n.display_name?.trim();return e?`${e} (${n.id})`:n.id}function Pn(n,e){let t=parseInt(n,10);if(Number.isNaN(t)||t<1)throw new Error(`${e} must be a positive integer`);return t}function Qe(n){console.log(JSON.stringify(n,null,2))}import{stdin as k,stdout as ye}from"node:process";import{createInterface as Gs}from"node:readline/promises";import{mkdir as vn,mkdtemp as Hs,rm as js}from"node:fs/promises";import Ws from"node:os";import xt from"node:path";function xn(n){let e=n.command("lucidlink").description("LucidLink auth and diagnostics");e.command("login").description("Validate LucidLink credentials and store reusable auth").option("--filespace <filespace>","LucidLink filespace identifier: <filespace>.<workspace>").option("--user <user>","LucidLink filespace user").option("--password-file <path>","File containing the LucidLink password").option("--instance <number>","LucidLink daemon instance ID for validation","9001").action(async i=>{await qs(i)});let t=Ut(e.command("doctor").description("Check LucidLink runner readiness and source access"));Dt(t).action(async i=>{let o=R({tempDir:i.tempDir,session:i.session,commandName:"lucidlink-doctor"});await V({sourceConfig:he({options:i,localTempDir:o.localTempDir}),localTempDir:o.localTempDir,tuningWarnings:ei(i)})});let r=Ut(e.command("list").description("List planned LucidLink source files before syncing")).option("--sample-size <number>","Number of planned paths to print","20");Dt(r).action(async i=>{let o=R({tempDir:i.tempDir,session:i.session,commandName:"lucidlink-list"});await Q({sourceConfig:he({options:i,localTempDir:o.localTempDir}),sampleSize:P(i.sampleSize,"--sample-size")})});let s=Ut(e.command("probe").description("Measure LucidLink source read throughput without uploading to Aspect")).option("--max-files <number>","Maximum files to read for the probe","1").option("--max-bytes <size>","Soft maximum bytes to read for the probe").option("--keep-local","Keep helper temp files in the temp directory",!1);Dt(s).action(async i=>{let o=R({tempDir:i.tempDir,session:i.session,commandName:"lucidlink-probe"});await J({sourceConfig:he({options:i,localTempDir:o.localTempDir}),localTempDir:o.localTempDir,maxFiles:P(i.maxFiles,"--max-files"),maxBytes:Y(i.maxBytes,"--max-bytes"),keepLocal:i.keepLocal})})}async function qs(n,e={}){let t=e.prompts??Qs(),r=await Ln({value:n.filespace,optionName:"--filespace",promptMessage:"LucidLink filespace (<filespace>.<workspace>): ",promptText:t.promptText}),s=await Ln({value:n.user,optionName:"--user",promptMessage:"LucidLink user: ",promptText:t.promptText}),i=n.passwordFile?yn(n.passwordFile):await Vs(t.promptPassword),o={filespace:r,user:s,password:i},a=n.authFile??de(),l=Zs(n.instance,"--instance");console.log(`Validating LucidLink filespace ${r}...`),await Ks({authFile:o,instanceId:l,createDaemon:e.createDaemon}),await gn(a,o),console.log(`Saved LucidLink auth to ${a}`)}async function Ks(n){let e=await Hs(xt.join(Ws.tmpdir(),"aspect-sync-lucidlink-login-")),t=xt.join(e,"mnt"),r=xt.join(e,"cache"),i=(n.createDaemon??(a=>new j(a)))({filespace:n.authFile.filespace,user:n.authFile.user,password:n.authFile.password,instanceId:n.instanceId,mountPoint:t,cacheRootPath:r}),o;try{await i.checkClientInstalled(),await vn(t,{recursive:!0}),await vn(r,{recursive:!0}),await i.start()}catch(a){throw o=a,a}finally{try{await Ys({daemon:i,validationError:o})}finally{await js(e,{recursive:!0,force:!0})}}}async function Ys(n){try{await n.daemon.stop()}catch(e){if(!n.validationError)throw e;console.error(`Failed to stop LucidLink validation daemon: ${e.message}`)}}async function Ln(n){let t=(n.value??await n.promptText(n.promptMessage)).trim();if(!t)throw new Error(`${n.optionName} cannot be empty`);return t}async function Vs(n){let e=await n("LucidLink password: ");if(!e)throw new Error("--password-file or password prompt cannot be empty");return e}function Qs(){return{promptText:Js,promptPassword:Xs}}async function Js(n){let e=Gs({input:k,output:ye});try{return await e.question(n)}finally{e.close()}}function Xs(n){if(!k.isTTY||!ye.isTTY)throw new Error("Interactive LucidLink password prompt requires a TTY; provide --password-file");return new Promise((e,t)=>{let r=[],s=k.isRaw,i=()=>{k.off("data",o),k.setRawMode(s),k.pause()},o=a=>{let l=a.toString("utf-8");for(let c of l){if(c===""){i(),ye.write(`
|
|
30
|
+
`)}async function mo(n){await Ot(n.localTempDir,{recursive:!0});let e=Fe.join(n.localTempDir,"probe"),t=Fe.join(n.localTempDir,"probe-files.txt");if(ho(n.sourceConfig))return await Ot(e,{recursive:!0}),await n.source.materializeBatch({files:n.files,batchDir:e,batchFilePath:t}),tt(n.files);let r=0;for(let s of n.files){let o=n.source.resolveLocalFile(s,e);r+=await fo(o.absolutePath)}return r}function ho(n){switch(n.kind){case"rclone":case"frameio":return!0;case"local":case"lucidlink":return!1;default:{let e=n;throw new Error(`Unsupported source kind: ${JSON.stringify(e)}`)}}}async function fo(n){return await new Promise((e,t)=>{let r=ao(n),s=0;r.on("data",o=>{s+=Buffer.isBuffer(o)?o.length:Buffer.byteLength(o)}),r.on("error",t),r.on("end",()=>e(s))})}function go(n){let e=[],t=0;for(let r of n.files){if(e.length>=n.maxFiles||n.maxBytes!==void 0&&e.length>0&&t+r.size>n.maxBytes)break;e.push(r),t+=r.size}return e}async function Kn(n){await Ot(n,{recursive:!0});let e=Fe.join(n,`.aspect-sync-write-test-${process.pid}-${Date.now()}`);await lo(e,"","utf-8"),await Bt(e,{force:!0})}function yo(n){return n.kind!=="lucidlink"?[]:[n.cacheRootPath]}function So(n){let e=F(n);return e===n.path?e:`${n.path} -> ${e}`}function tt(n){return n.reduce((e,t)=>e+t.size,0)}function Co(n){let e=new Date().toISOString().replace(/[:.]/g,"-");return`${n}-${e}`}function Qn(n){let e=n.command("frameio").description("Frame.io auth, discovery, and bandwidth diagnostics");e.command("login").description("Authenticate to Frame.io V4 via Adobe OAuth PKCE and store refresh credentials").option("--client-id <id>","Adobe OAuth client ID",hn()).action(async s=>{await Eo(s)}),e.command("accounts").description("List Frame.io accounts accessible to the current token").action(async s=>{let i=await(await nt(s)).listAccounts();rt(i)}),e.command("workspaces").description("List workspaces in the login-selected Frame.io account").action(async s=>{let o=await nt(s),i=await zt(s),a=await o.listWorkspaces(i);rt(a)}),e.command("projects").description("List Frame.io projects in the login-selected account").option("--workspace-id <id>","Optionally scope projects to a Frame.io workspace ID").option("--page-size <number>","Frame.io page size","100").action(async s=>{let o=await nt(s),i=await zt(s),a=Yn(s.pageSize,"--page-size"),l=s.workspaceId?await o.listProjects({accountId:i,workspaceId:s.workspaceId,pageSize:a}):await o.listAccountProjects({accountId:i,pageSize:a});rt(l)}),e.command("folders").description("List children in a Frame.io folder in the login-selected account").requiredOption("--folder-id <id>","Frame.io folder ID").option("--page-size <number>","Frame.io page size","100").action(async s=>{let o=await nt(s),i=await zt(s),a=await o.listFolderChildren({accountId:i,folderId:s.folderId,pageSize:Yn(s.pageSize,"--page-size")});rt(a)});let t=Nt(e.command("doctor").description("Check Frame.io auth, account, and source folder access"));Jn(t).action(async s=>{let o=I({tempDir:s.tempDir,session:s.session,commandName:"frameio-doctor"});await X({sourceConfig:Ae({options:s}),localTempDir:o.localTempDir})}),Nt(e.command("list").description("List planned Frame.io source files before syncing")).option("--sample-size <number>","Number of planned paths to print","20").action(async s=>{await Z({sourceConfig:Ae({options:s}),sampleSize:R(s.sampleSize,"--sample-size")})});let r=Nt(e.command("probe").description("Measure Frame.io original download throughput without uploading to Aspect")).option("--max-files <number>","Maximum files to download for the probe","1").option("--max-bytes <size>","Soft maximum bytes to download for the probe").option("--keep-local","Keep downloaded probe files in the temp directory",!1);Jn(r).action(async s=>{let o=I({tempDir:s.tempDir,session:s.session,commandName:"frameio-probe"});await ee({sourceConfig:Ae({options:s}),localTempDir:o.localTempDir,maxFiles:R(s.maxFiles,"--max-files"),maxBytes:V(s.maxBytes,"--max-bytes"),keepLocal:s.keepLocal})})}function Nt(n){return n.requiredOption("--source-folder-id <id>","Frame.io folder ID to use as the source root").option("--frameio-download-concurrent <number>","Concurrent Frame.io original downloads","4").option("--frameio-page-size <number>","Frame.io folder listing page size","100")}function Jn(n){return n.option("--temp-dir <path>","Local temporary directory for helper downloads and checks").option("--session <name>","Session name for helper temp paths")}async function Eo(n){let e=fn(),t=gn({clientId:n.clientId,codeChallenge:e.challenge});console.log("Open this URL in a browser and approve access:"),console.log(t),console.log("");let r=await Vn("Paste the full redirected URL or code: "),s=yn(r),o=await Sn({clientId:n.clientId,code:s,codeVerifier:e.verifier}),a=await new z({token:o.access_token}).listAccounts(),l=await wo({accounts:a}),c=J();await Tt(c,kt({clientId:n.clientId,token:o,defaultAccountId:l})),console.log(`Saved Frame.io auth to ${c}`)}async function nt(n){let e=await je();return new z({token:e})}async function zt(n){let e=J(),t=await Rt(e);if(t.defaultAccountId)return t.defaultAccountId;throw new Error("Frame.io default account ID is missing; run aspect-sync frameio login.")}async function wo(n){if(n.accounts.length===0)throw new Error("Frame.io login did not return any accessible accounts");let e=n.writeOutput??(r=>console.log(r));if(n.accounts.length===1){let r=n.accounts[0];return e(`Selected default Frame.io account: ${Gt(r)}`),r.id}let t=n.promptForInput??Vn;for(e("Select the default Frame.io account for sync:"),n.accounts.forEach((r,s)=>{e(`${s+1}. ${Gt(r)}`)});;){let r=(await t("Account number or ID: ")).trim(),s=Io(n.accounts,r);if(s)return e(`Selected default Frame.io account: ${Gt(s)}`),s.id;e("Invalid account selection. Enter a listed number or account ID.")}}async function Vn(n){let e=bo({input:Ao,output:Fo});try{return await e.question(n)}finally{e.close()}}function Io(n,e){let t=Number.parseInt(e,10);return String(t)===e&&t>=1&&t<=n.length?n[t-1]:n.find(r=>r.id===e)}function Gt(n){let e=n.display_name?.trim();return e?`${e} (${n.id})`:n.id}function Yn(n,e){let t=parseInt(n,10);if(Number.isNaN(t)||t<1)throw new Error(`${e} must be a positive integer`);return t}function rt(n){console.log(JSON.stringify(n,null,2))}import{stdin as T,stdout as Ee}from"node:process";import{createInterface as Po}from"node:readline/promises";import{mkdir as Xn,mkdtemp as Ro,rm as To}from"node:fs/promises";import ko from"node:os";import $t from"node:path";function er(n){let e=n.command("lucidlink").description("LucidLink auth and diagnostics");e.command("login").description("Validate LucidLink credentials and store reusable auth").option("--filespace <filespace>","LucidLink filespace identifier: <filespace>.<workspace>").option("--user <user>","LucidLink filespace user").option("--password-file <path>","File containing the LucidLink password").option("--instance <number>","LucidLink daemon instance ID for validation","9001").action(async o=>{await vo(o)});let t=jt(e.command("doctor").description("Check LucidLink runner readiness and source access"));Ht(t).action(async o=>{let i=I({tempDir:o.tempDir,session:o.session,commandName:"lucidlink-doctor"});await X({sourceConfig:be({options:o,localTempDir:i.localTempDir}),localTempDir:i.localTempDir,tuningWarnings:Mo(o)})});let r=jt(e.command("list").description("List planned LucidLink source files before syncing")).option("--sample-size <number>","Number of planned paths to print","20");Ht(r).action(async o=>{let i=I({tempDir:o.tempDir,session:o.session,commandName:"lucidlink-list"});await Z({sourceConfig:be({options:o,localTempDir:i.localTempDir}),sampleSize:R(o.sampleSize,"--sample-size")})});let s=jt(e.command("probe").description("Measure LucidLink source read throughput without uploading to Aspect")).option("--max-files <number>","Maximum files to read for the probe","1").option("--max-bytes <size>","Soft maximum bytes to read for the probe").option("--keep-local","Keep helper temp files in the temp directory",!1);Ht(s).action(async o=>{let i=I({tempDir:o.tempDir,session:o.session,commandName:"lucidlink-probe"});await ee({sourceConfig:be({options:o,localTempDir:i.localTempDir}),localTempDir:i.localTempDir,maxFiles:R(o.maxFiles,"--max-files"),maxBytes:V(o.maxBytes,"--max-bytes"),keepLocal:o.keepLocal})})}async function vo(n,e={}){let t=e.prompts??Do(),r=await Zn({value:n.filespace,optionName:"--filespace",promptMessage:"LucidLink filespace (<filespace>.<workspace>): ",promptText:t.promptText}),s=await Zn({value:n.user,optionName:"--user",promptMessage:"LucidLink user: ",promptText:t.promptText}),o=n.passwordFile?Nn(n.passwordFile):await xo(t.promptPassword),i={filespace:r,user:s,password:o},a=n.authFile??ye(),l=Bo(n.instance,"--instance");console.log(`Validating LucidLink filespace ${r}...`),await Uo({authFile:i,instanceId:l,createDaemon:e.createDaemon}),await Mn(a,i),console.log(`Saved LucidLink auth to ${a}`)}async function Uo(n){let e=await Ro($t.join(ko.tmpdir(),"aspect-sync-lucidlink-login-")),t=$t.join(e,"mnt"),r=$t.join(e,"cache"),o=(n.createDaemon??(a=>new q(a)))({filespace:n.authFile.filespace,user:n.authFile.user,password:n.authFile.password,instanceId:n.instanceId,mountPoint:t,cacheRootPath:r}),i;try{await o.checkClientInstalled(),await Xn(t,{recursive:!0}),await Xn(r,{recursive:!0}),await o.start()}catch(a){throw i=a,a}finally{try{await Lo({daemon:o,validationError:i})}finally{await To(e,{recursive:!0,force:!0})}}}async function Lo(n){try{await n.daemon.stop()}catch(e){if(!n.validationError)throw e;console.error(`Failed to stop LucidLink validation daemon: ${e.message}`)}}async function Zn(n){let t=(n.value??await n.promptText(n.promptMessage)).trim();if(!t)throw new Error(`${n.optionName} cannot be empty`);return t}async function xo(n){let e=await n("LucidLink password: ");if(!e)throw new Error("--password-file or password prompt cannot be empty");return e}function Do(){return{promptText:_o,promptPassword:Oo}}async function _o(n){let e=Po({input:T,output:Ee});try{return await e.question(n)}finally{e.close()}}function Oo(n){if(!T.isTTY||!Ee.isTTY)throw new Error("Interactive LucidLink password prompt requires a TTY; provide --password-file");return new Promise((e,t)=>{let r=[],s=T.isRaw,o=()=>{T.off("data",i),T.setRawMode(s),T.pause()},i=a=>{let l=a.toString("utf-8");for(let c of l){if(c===""){o(),Ee.write(`
|
|
25
31
|
`),t(new Error("LucidLink password prompt cancelled"));return}if(c==="\r"||c===`
|
|
26
|
-
`){
|
|
27
|
-
`),e(r.join(""));return}if(c==="\x7F"){r.pop();continue}c>=" "&&r.push(c)}};
|
|
28
|
-
${s.trim()}`:"")))}),r.on("error",
|
|
32
|
+
`){o(),Ee.write(`
|
|
33
|
+
`),e(r.join(""));return}if(c==="\x7F"){r.pop();continue}c>=" "&&r.push(c)}};Ee.write(n),T.setRawMode(!0),T.resume(),T.on("data",i)})}function Bo(n,e){let t=parseInt(n,10);if(Number.isNaN(t)||t<1)throw new Error(`${e} must be a positive integer`);return t}function jt(n){return n.requiredOption("--source-path <path>","path within the LucidLink filespace").option("--lucid-instance <number>","LucidLink daemon instance ID","9001").option("--lucid-cache-size <size>","LucidLink DataCache.Size applied after mount")}function Ht(n){return n.option("--temp-dir <path>","Local temporary directory for helper reads and checks").option("--session <name>","Session name for helper temp paths")}function Mo(n){return n.lucidCacheSize?[]:["--lucid-cache-size is not set; LucidLink will use its current local cache configuration."]}import{spawn as No}from"node:child_process";function nr(n){let e=n.command("rclone").description("rclone auth validation and source diagnostics");e.command("login").description("Validate a native rclone remote for reuse by aspect-sync").requiredOption("--remote <remote>","rclone remote name (e.g., dropbox)").action(async s=>{await zo(s)});let t=Wt(e.command("doctor").description("Check rclone runner readiness and source access"));tr(t).action(async s=>{let o=I({tempDir:s.tempDir,session:s.session,commandName:"rclone-doctor"});await X({sourceConfig:Ce(s),localTempDir:o.localTempDir,tuningWarnings:Go(s)})}),Wt(e.command("list").description("List planned rclone source files before syncing")).option("--sample-size <number>","Number of planned paths to print","20").action(async s=>{await Z({sourceConfig:Ce(s),sampleSize:R(s.sampleSize,"--sample-size")})});let r=Wt(e.command("probe").description("Measure rclone source download throughput without uploading to Aspect")).option("--max-files <number>","Maximum files to download for the probe","1").option("--max-bytes <size>","Soft maximum bytes to download for the probe").option("--keep-local","Keep downloaded probe files in the temp directory",!1);tr(r).action(async s=>{let o=I({tempDir:s.tempDir,session:s.session,commandName:"rclone-probe"});await ee({sourceConfig:Ce(s),localTempDir:o.localTempDir,maxFiles:R(s.maxFiles,"--max-files"),maxBytes:V(s.maxBytes,"--max-bytes"),keepLocal:s.keepLocal})})}async function zo(n){await Be(),await $o(n.remote),console.log(`rclone remote "${n.remote}" is configured and ready for aspect-sync.`)}function Wt(n){return n.requiredOption("--remote <remote>","rclone remote name (e.g., dropbox)").requiredOption("--source-path <path>","path within the rclone remote").option("--rclone-transfers <number>","Number of parallel file transfers","4").option("--rclone-multi-thread-streams <number>","Streams per large file","4").option("--rclone-multi-thread-chunk-size <size>","Chunk size for multi-threading","64MiB").option("--rclone-multi-thread-cutoff <size>","Minimum file size for multi-threading","64MiB").option("--rclone-buffer-size <size>","Buffer size per transfer","64M").option("--rclone-no-mmap","Disable memory-mapped I/O",!1).option("--rclone-extra <arg>","Additional rclone argument to append (repeatable)",(e,t)=>(t??[]).concat(e),[])}function tr(n){return n.option("--temp-dir <path>","Local temporary directory for helper downloads and checks").option("--session <name>","Session name for helper temp paths")}function Go(n){let e=[],t=Number.parseInt(n.rcloneTransfers??"4",10);return Number.isFinite(t)&&t>=32&&e.push("--rclone-transfers is high; confirm the source provider and runner network can sustain this concurrency."),n.rcloneNoMmap===!0&&e.push("--rclone-no-mmap reduces memory efficiency and should only be used for known mmap issues."),e}function $o(n){return new Promise((e,t)=>{let r=No("rclone",["config","show",n],{stdio:["ignore","pipe","pipe"]}),s="";r.stderr?.on("data",o=>{s+=o.toString()}),r.on("close",o=>{if(o===0){e();return}t(new Error(`rclone remote "${n}" is not configured or could not be loaded. Run "rclone config" to create or repair the remote, then rerun "aspect-sync rclone login --remote ${n}".`+(s.trim()?`
|
|
34
|
+
${s.trim()}`:"")))}),r.on("error",o=>{t(new Error(`Failed to start rclone config validation: ${o.message}`))})})}function rr(n,e){let t=n.command("sync").description("Sync files from a source into Aspect");jo(t,e),Ho(t,e),Wo(t,e),Ko(t,e)}function jo(n,e){st(n.command("rclone").description("Sync from an rclone remote")).option("--remote <remote>","rclone remote name (e.g., dropbox)").option("--source-path <path>","path within the rclone remote to sync").option("--rclone-transfers <number>","Number of parallel file transfers (default: 4)","4").option("--rclone-multi-thread-streams <number>","Streams per large file (default: 4, higher = faster large files)","4").option("--rclone-multi-thread-chunk-size <size>","Chunk size for multi-threading (default: 64MiB)","64MiB").option("--rclone-multi-thread-cutoff <size>","Minimum file size for multi-threading (default: 64MiB)","64MiB").option("--rclone-buffer-size <size>","Buffer size per transfer (default: 64M, memory = transfers x buffer-size)","64M").option("--rclone-no-mmap","Disable memory-mapped I/O (reduces memory efficiency)",!1).option("--rclone-extra <arg>","Additional rclone argument to append (repeatable)",(r,s)=>(s??[]).concat(r),[]).action(async r=>{await e({commandOptions:r,buildConfig:s=>$n({options:r,environment:s})})})}function Ho(n,e){st(n.command("local").description("Sync from a local directory")).option("--source-path <path>","local directory to sync").action(async r=>{await e({commandOptions:r,buildConfig:s=>jn({options:r,environment:s})})})}function Wo(n,e){st(n.command("lucidlink").description("Sync from a LucidLink filespace")).option("--source-path <path>","path within the LucidLink filespace to sync").option("--lucid-instance <number>","LucidLink daemon instance ID (default: 9001)","9001").option("--lucid-cache-size <size>","LucidLink DataCache.Size applied after mount (e.g., 100GB)").action(async r=>{await e({commandOptions:r,buildConfig:s=>Hn({options:r,environment:s})})})}function Ko(n,e){st(n.command("frameio").description("Sync from a Frame.io folder")).option("--source-folder-id <id>","Frame.io folder ID to use as the source root").option("--frameio-download-concurrent <number>","Concurrent Frame.io original downloads (default: 4)","4").option("--frameio-page-size <number>","Frame.io folder listing page size (default: 100)","100").action(async r=>{await e({commandOptions:r,buildConfig:s=>Wn({options:r,environment:s})})})}function st(n){return n.option("--asp-directory-id <id>","Aspect directory ID to upload to").option("--asp-project-id <id>","Aspect project ID").option("--asp-api-url <url>","Aspect API URL").option("--asp-edge-worker-url <url>","Aspect edge worker URL").option("--asp-api-key <key>","Aspect API key").option("--upload-concurrent <number>","Maximum concurrent chunk uploads to Aspect (default: 16)","16").option("--keep-local","Keep local files after upload (for debugging)",!1).option("--temp-dir <path>","Local temporary directory for synced files").option("--session <name>","Session name for isolation (default: auto-generated timestamp)").option("--check","Check remote files against Aspect without downloading/uploading",!1).option("--batch-size <size>","Enable batched mode with max batch size (e.g., 500GB, 1TB). Helps with large migrations.","").option("--shard-count <number>","Split the planned file list across this many concurrent sessions").option("--shard-index <number>","Zero-based shard index for this session").option("--progress <human|json>","Progress output mode. json emits one NDJSON event per line.","human")}var ir=Yo(import.meta.url),Qo=or.dirname(ir),ar=JSON.parse(Jo(or.join(Qo,"..","package.json"),"utf-8"));function Vo(n={}){let e=new qo;return e.name("aspect-sync").description("Sync files from external services to Aspect").version(n.packageVersion??ar.version),e.command("login").description("Store Aspect API credentials for sync commands").option("--asp-api-key <key>","Aspect API key").option("--asp-api-url <url>","Aspect API URL").option("--asp-edge-worker-url <url>","Aspect edge worker URL").action(async t=>{await vn(t)}),Qn(e),er(e),nr(e),rr(e,n.executeSyncCommand??Xo(n)),e}function Xo(n){return async e=>{await Zo({execution:e,environment:n.getEnvironment?.()??ei()})}}async function Zo(n){let e=0;try{let t=n.execution.buildConfig(n.environment),r=ti(t),s=await ni(t,r);s&&en({config:t,packageVersion:ar.version,user:s});let o=new Xe(t,r);n.execution.commandOptions.check?await o.runCheckOnly():t.batchSizeBytes!==void 0?await o.runBatched():await o.run()}catch(t){console.error("Fatal error:",t),e=1}finally{await nn()}process.exit(e)}function ei(){return{ASPECT_API_URL:process.env.ASPECT_API_URL,ASPECT_EDGE_WORKER_URL:process.env.ASPECT_EDGE_WORKER_URL,ASPECT_API_KEY:process.env.ASPECT_API_KEY,ASPECT_POSTHOG_KEY:process.env.ASPECT_POSTHOG_KEY,ASPECT_POSTHOG_HOST:process.env.ASPECT_POSTHOG_HOST,ASPECT_DISABLE_POSTHOG:process.env.ASPECT_DISABLE_POSTHOG,POSTHOG_KEY:process.env.POSTHOG_KEY,POSTHOG_API_KEY:process.env.POSTHOG_API_KEY,POSTHOG_HOST:process.env.POSTHOG_HOST,POSTHOG_DISABLED:process.env.POSTHOG_DISABLED}}ri()&&await Vo().parseAsync();function ti(n){return new x({apiUrl:n.apiUrl,apiKey:n.apiKey,edgeWorkerUrl:n.edgeWorkerUrl,sessionId:n.sessionName})}async function ni(n,e){return n.analytics.disabled||!n.analytics.posthogKey?null:await e.get("/users/me")}function ri(){let n=process.argv[1];return n===void 0?!1:sr(n)===sr(ir)}export{Vo as createProgram};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aspect-sync",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"description": "CLI tool to sync files from external services to Aspect via rclone",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
],
|
|
15
15
|
"type": "module",
|
|
16
16
|
"scripts": {
|
|
17
|
+
"prebuild": "npm --prefix ../shared run build",
|
|
17
18
|
"build": "tsc && node scripts/build.mjs",
|
|
18
19
|
"build:watch": "tsc --watch",
|
|
19
20
|
"dev": "tsx src/index.ts",
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
"license": "MIT",
|
|
33
34
|
"homepage": "https://aspect.inc",
|
|
34
35
|
"dependencies": {
|
|
36
|
+
"@aspect/migration-shared": "file:../shared",
|
|
35
37
|
"axios": "^1.11.0",
|
|
36
38
|
"chalk": "^5.3.0",
|
|
37
39
|
"commander": "^12.0.0",
|
|
@@ -39,8 +41,8 @@
|
|
|
39
41
|
"posthog-node": "^5.34.1"
|
|
40
42
|
},
|
|
41
43
|
"devDependencies": {
|
|
42
|
-
"@aspect/transfer-utils": "file
|
|
43
|
-
"@aspect/upload-core": "file
|
|
44
|
+
"@aspect/transfer-utils": "file:../../packages/transfer-utils",
|
|
45
|
+
"@aspect/upload-core": "file:../../packages/upload-core",
|
|
44
46
|
"@types/node": "^22.0.0",
|
|
45
47
|
"esbuild": "^0.28.0",
|
|
46
48
|
"tsx": "^4.7.0",
|