@shumai-one/shumai-cli 0.4.1 → 0.4.3

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.
Files changed (2) hide show
  1. package/bin/shumai-cli.js +14 -11
  2. package/package.json +1 -1
package/bin/shumai-cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- function _(e){return e.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,"")}function F(e){let t=_(e),r=0;for(let s=0;s<t.length;s++){let o=t.charCodeAt(s);if(o>=12288&&o<=40959||o>=65280&&o<=65519||o>=4352&&o<=4607||o>=44032&&o<=55215)r+=2;else r+=1}return r}function G(e,t){let r=_(t);if(F(r)<=e)return t;if(e<=3)return".".repeat(e);let o=e-3,a=0,c=0;for(let l=0;l<t.length;l++){if(t[l]==="\x1B"){let f=t.slice(l).match(/^[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/);if(f){l+=f[0].length-1;continue}}let n=t.charCodeAt(l),i=n>=12288&&n<=40959||n>=65280&&n<=65519||n>=4352&&n<=4607||n>=44032&&n<=55215?2:1;if(a+i>o){c=l;break}a+=i}let p=t.slice(0,c),g=t.includes("\x1B")?"\x1B[0m":"";return p+"..."+g}function R(e,t){let r=F(t);if(r>=e)return t;return t+" ".repeat(e-r)}function z(e){return(t)=>{t.truncateFunc=e??void 0}}function O(e,t,r){if(t)return new U(e,r);return new I(e)}class U{out;maxWidth;hasHeaders=!1;rows=[];constructor(e,t){this.out=e;this.maxWidth=t}addHeader(e,...t){if(this.hasHeaders)return;this.hasHeaders=!0;for(let r of e)this.addField(r,...t);this.endRow()}addField(e,...t){if(this.rows.length===0)this.rows.push([]);let r=this.rows.length-1,s={text:e,truncateFunc:G};for(let o of t)o(s);this.rows[r].push(s)}endRow(){this.rows.push([])}render(){let e=this.rows.filter((o)=>o.length>0);if(e.length===0)return;let t=" ",r=e[0].length,s=this.calculateColumnWidths(e,t.length);for(let o of e){for(let a=0;a<o.length;a++){if(a>=r)break;let c=o[a];if(a>0)this.out.write(t);let p=c.text;if(c.truncateFunc)p=c.truncateFunc(s[a],c.text);if(c.paddingFunc)p=c.paddingFunc(s[a],p);else if(a<r-1)p=R(s[a],p);if(c.colorFunc)p=c.colorFunc(p);this.out.write(p)}if(o.length>0)this.out.write(`
3
- `)}}calculateColumnWidths(e,t){let r=e[0].length,s=Array(r).fill(0),o=Array(r).fill(0);for(let l of e)for(let n=0;n<l.length;n++){if(n>=r)break;let i=l[n],f=F(i.text);if(f>s[n])s[n]=f;if(i.truncateFunc===void 0&&f>o[n])o[n]=f}let a=()=>{let l=0;for(let n=0;n<r;n++)l+=o[n];return this.maxWidth-t*(r-1)-l},c=()=>{let l=0;for(let n=0;n<r;n++)if(o[n]>0)l++;return l},p=a();if(p>0){let l=r-c();if(l>0){let n=Math.floor(p/l);for(let i=0;i<r;i++)if(o[i]===0){let f=s[i];if(f<n)o[i]=f}}}p=a();let g=r-c();if(g>0){let l=Math.floor(p/g);for(let n=0;n<r;n++)if(o[n]===0){let i=s[n];if(i<l)o[n]=i;else if(l>0)o[n]=l}}if(p=a(),p>0)for(let l=0;l<r;l++){let n=s[l]-o[l],i=p;if(n<i)i=n;if(o[l]+=i,p-=i,p<=0)break}return o}}class I{out;currentCol=0;constructor(e){this.out=e}addHeader(){}addField(e){if(this.currentCol>0)this.out.write("\t");this.out.write(e),this.currentCol++}endRow(){this.out.write(`
4
- `),this.currentCol=0}render(){}}var de=/^[\w!#$%&'*.^`|~+-]+$/;var ge=(e,t,r={})=>{if(!de.test(e))throw Error("Invalid cookie name");let s=`${e}=${t}`;if(e.startsWith("__Secure-")&&!r.secure)throw Error("__Secure- Cookie must have Secure attributes");if(e.startsWith("__Host-")){if(!r.secure)throw Error("__Host- Cookie must have Secure attributes");if(r.path!=="/")throw Error('__Host- Cookie must have Path attributes with "/"');if(r.domain)throw Error("__Host- Cookie must not have Domain attributes")}for(let o of["domain","path","sameSite","priority"])if(r[o]&&/[;\r\n]/.test(r[o]))throw Error(`${o} must not contain ";", "\\r", or "\\n"`);if(r&&typeof r.maxAge==="number"&&r.maxAge>=0){if(r.maxAge>34560000)throw Error("Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration.");s+=`; Max-Age=${r.maxAge|0}`}if(r.domain&&r.prefix!=="host")s+=`; Domain=${r.domain}`;if(r.path)s+=`; Path=${r.path}`;if(r.expires){if(r.expires.getTime()-Date.now()>34560000000)throw Error("Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future.");s+=`; Expires=${r.expires.toUTCString()}`}if(r.httpOnly)s+="; HttpOnly";if(r.secure)s+="; Secure";if(r.sameSite)s+=`; SameSite=${r.sameSite.charAt(0).toUpperCase()+r.sameSite.slice(1)}`;if(r.priority)s+=`; Priority=${r.priority.charAt(0).toUpperCase()+r.priority.slice(1)}`;if(r.partitioned){if(!r.secure)throw Error("Partitioned Cookie must have Secure attributes");s+="; Partitioned"}return s},W=(e,t,r)=>{return t=encodeURIComponent(t),ge(e,t,r)};var E=(e,t)=>{return e=e.replace(/\/+$/,""),e=e+"/",t=t.replace(/^\/+/,""),e+t},b=(e,t)=>{for(let[r,s]of Object.entries(t)){let o=new RegExp("/:"+r+"(?:{[^/]+})?\\??");e=e.replace(o,s?`/${s}`:"")}return e},C=(e)=>{let t=new URLSearchParams;for(let[r,s]of Object.entries(e)){if(s===void 0)continue;if(Array.isArray(s))for(let o of s)t.append(r,o);else t.set(r,s)}return t},N=(e,t)=>{switch(t){case"ws":return e.replace(/^http/,"ws");case"http":return e.replace(/^ws/,"http")}},Q=(e)=>{if(/^https?:\/\/[^\/]+?\/index(?=\?|$)/.test(e))return e.replace(/\/index(?=\?|$)/,"/");return e.replace(/\/index(?=\?|$)/,"")};function A(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function J(e,t){if(!A(e)&&!A(t))return t;let r={...e};for(let s in t){let o=t[s];if(A(r[s])&&A(o))r[s]=J(r[s],o);else r[s]=o}return r}var D=(e,t)=>{return new Proxy(()=>{},{get(s,o){if(typeof o!=="string"||o==="then")return;return D(e,[...t,o])},apply(s,o,a){return e({path:t,args:a})}})},he=class{url;method;buildSearchParams;queryParams=void 0;pathParams={};rBody;cType=void 0;constructor(e,t,r){this.url=e,this.method=t,this.buildSearchParams=r.buildSearchParams}fetch=async(e,t)=>{if(e){if(e.query)this.queryParams=this.buildSearchParams(e.query);if(e.form){let p=new FormData;for(let[g,l]of Object.entries(e.form)){if(l===void 0)continue;if(Array.isArray(l))for(let n of l)p.append(g,n);else p.append(g,l)}this.rBody=p}if(e.json)this.rBody=JSON.stringify(e.json),this.cType="application/json";if(e.param)this.pathParams=e.param}let r=this.method.toUpperCase(),s={...e?.header,...typeof t?.headers==="function"?await t.headers():t?.headers};if(e?.cookie){let p=[];for(let[g,l]of Object.entries(e.cookie))p.push(W(g,l,{path:"/"}));s.Cookie=p.join(",")}if(this.cType)s["Content-Type"]=this.cType;let o=new Headers(s??void 0),a=this.url;if(a=Q(a),a=b(a,this.pathParams),this.queryParams)a=a+"?"+this.queryParams.toString();r=this.method.toUpperCase();let c=!(r==="GET"||r==="HEAD");return(t?.fetch||fetch)(a,{body:c?this.rBody:void 0,method:r,headers:o,...t?.init})}},V=(e,t)=>D(function r(s){let o=t?.buildSearchParams??C,a=[...s.path],c=a.slice(-3).reverse();if(c[0]==="toString"){if(c[1]==="name")return c[2]||"";return r.toString()}if(c[0]==="valueOf"){if(c[1]==="name")return c[2]||"";return r}let p="";if(/^\$/.test(c[0])){let i=a.pop();if(i)p=i.replace(/^\$/,"")}let g=a.join("/"),l=E(e,g);if(p==="url"||p==="path"){let i=l;if(s.args[0]){if(s.args[0].param)i=b(l,s.args[0].param);if(s.args[0].query)i=i+"?"+o(s.args[0].query).toString()}if(i=Q(i),p==="url")return new URL(i);return i.slice(e.replace(/\/+$/,"").length).replace(/^\/?/,"/")}if(p==="ws"){let i=N(s.args[0]&&s.args[0].param?b(l,s.args[0].param):l,"ws"),f=new URL(i),u=s.args[0]?.query;if(u)Object.entries(u).forEach(([d,v])=>{if(Array.isArray(v))v.forEach((P)=>f.searchParams.append(d,P));else f.searchParams.set(d,v)});return((...d)=>{if(t?.webSocket!==void 0&&typeof t.webSocket==="function")return t.webSocket(...d);return new WebSocket(...d)})(f.toString())}let n=new he(l,p,{buildSearchParams:o});if(p){t??={};let i=J(t,{...s.args[1]});return n.fetch(s.args[0],i)}return n},[]);function k(){let e=process.env.SHUMAI_API_KEY,t=process.env.SHUMAI_API_SERVER;if(!t)console.error("Error: SHUMAI_API_SERVER environment variable is not set."),process.exit(1);if(!e)console.error("Error: SHUMAI_API_KEY environment variable is not set. Please generate a token in the Settings -> Developer tab."),process.exit(1);return V(t,{headers:{Authorization:`Bearer ${e}`}})}async function L(){let e=k();try{let t=await e.api.projects.$get({query:{first:"200"}});if(!t.ok){let c=await t.json().catch(()=>({error:"Unknown error"}));console.error(`Error: ${c.error||"Failed to list projects"}`),process.exit(1)}let{data:r}=await t.json();if(r.length===0){console.log("No projects found.");return}let s=process.stdout.isTTY,o=process.stdout.columns||80,a=O(process.stdout,s,o);a.addHeader(["ID","Name","Root Folder ID"]);for(let c of r)a.addField(c.id||""),a.addField(c.name||""),a.addField(c.rootFolder||""),a.endRow();a.render()}catch(t){console.error("Error connecting to API server:",t instanceof Error?t.message:t),process.exit(1)}}function ue(e){if(e===0)return"-";let t=1024,r=["B","KB","MB","GB","TB"],s=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,s)).toFixed(2))+" "+r[s]}async function ee(e){if(!e)console.error("Error: Parent ID (-p/--parent) is required."),process.exit(1);let t=k();try{let[r,s]=await Promise.all([t.api.folders[":folderId"].children.$get({param:{folderId:e},query:{assetType:"folder",first:"200"}}),t.api.folders[":folderId"].children.$get({param:{folderId:e},query:{assetType:"file",first:"200"}})]);if(!r.ok){let f=await r.json().catch(()=>({error:"Unknown error"}));console.error(`Error: ${f.error||"Failed to list folders"}`),process.exit(1)}if(!s.ok){let f=await s.json().catch(()=>({error:"Unknown error"}));console.error(`Error: ${f.error||"Failed to list files"}`),process.exit(1)}let o=await r.json(),a=await s.json(),c=o.data||[],p=a.data||[],g=[...c.map((f)=>({...f,typeDisplay:"folder"})),...p.map((f)=>({...f,typeDisplay:"file"}))];if(g.length===0){console.log("No assets found in this folder.");return}let l=process.stdout.isTTY,n=process.stdout.columns||80,i=O(process.stdout,l,n);i.addHeader(["ID","Name","Type","Size"]);for(let f of g)i.addField(f.id||"",z(null)),i.addField(f.name||""),i.addField(f.typeDisplay,z(null)),i.addField(f.typeDisplay==="folder"?"-":ue(f.sizeByte||0),z(null)),i.endRow();i.render()}catch(r){console.error("Error connecting to API server:",r instanceof Error?r.message:r),process.exit(1)}}async function re(e,t){if(!e)console.error("Error: Folder name is required."),process.exit(1);if(!t)console.error("Error: Parent ID (-p/--parent) is required."),process.exit(1);let r=k();try{let s=await r.api.folders.$post({json:{name:e,parentId:t}});if(!s.ok){let a=await s.json().catch(()=>({error:"Unknown error"}));console.error(`Error: ${a.error||"Failed to create folder"}`),process.exit(1)}let o=await s.json();console.log(`Created folder with ID: ${o.id}`)}catch(s){console.error("Error connecting to API server:",s instanceof Error?s.message:s),process.exit(1)}}import Z from"node:fs";import ae from"node:fs/promises";import we from"node:http";import Se from"node:https";import K from"node:path";import H from"node:crypto";var se="0123456789ABCDEFGHJKMNPQRSTVWXYZ",M=32;var ye=16,oe=10,te=281474976710655;var w;(function(e){e.Base32IncorrectEncoding="B32_ENC_INVALID",e.DecodeTimeInvalidCharacter="DEC_TIME_CHAR",e.DecodeTimeValueMalformed="DEC_TIME_MALFORMED",e.EncodeTimeNegative="ENC_TIME_NEG",e.EncodeTimeSizeExceeded="ENC_TIME_SIZE_EXCEED",e.EncodeTimeValueMalformed="ENC_TIME_MALFORMED",e.PRNGDetectFailure="PRNG_DETECT",e.ULIDInvalid="ULID_INVALID",e.Unexpected="UNEXPECTED",e.UUIDInvalid="UUID_INVALID"})(w||(w={}));class S extends Error{constructor(e,t){super(`${t} (${e})`);this.name="ULIDError",this.code=e}}function ve(e){let t=Math.floor(e()*M)%M;return se.charAt(t)}function xe(e){let t=ke(),r=t&&(t.crypto||t.msCrypto)||(typeof H<"u"?H:null);if(typeof r?.getRandomValues==="function")return()=>{let s=new Uint8Array(1);return r.getRandomValues(s),s[0]/256};else if(typeof r?.randomBytes==="function")return()=>r.randomBytes(1).readUInt8()/256;else if(H?.randomBytes)return()=>H.randomBytes(1).readUInt8()/256;throw new S(w.PRNGDetectFailure,"Failed to find a reliable PRNG")}function ke(){if(je())return self;if(typeof window<"u")return window;if(typeof global<"u")return global;if(typeof globalThis<"u")return globalThis;return null}function $e(e,t){let r="";for(;e>0;e--)r=ve(t)+r;return r}function Pe(e,t=oe){if(isNaN(e))throw new S(w.EncodeTimeValueMalformed,`Time must be a number: ${e}`);else if(e>te)throw new S(w.EncodeTimeSizeExceeded,`Cannot encode a time larger than ${te}: ${e}`);else if(e<0)throw new S(w.EncodeTimeNegative,`Time must be positive: ${e}`);else if(Number.isInteger(e)===!1)throw new S(w.EncodeTimeValueMalformed,`Time must be an integer: ${e}`);let r,s="";for(let o=t;o>0;o--)r=e%M,s=se.charAt(r)+s,e=(e-r)/M;return s}function je(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}function B(e,t){let r=t||xe(),s=!e||isNaN(e)?Date.now():e;return Pe(s,oe)+$e(ye,r)}function T(e){let t=K.extname(e).toLowerCase();return{".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".webp":"image/webp",".mp4":"video/mp4",".mkv":"video/x-matroska",".mov":"video/quicktime",".avi":"video/x-msvideo",".webm":"video/webm",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".txt":"text/plain",".md":"text/markdown",".markdown":"text/markdown",".json":"application/json",".pdf":"application/pdf",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip"}[t]||"application/octet-stream"}async function ne(e,t){let r=await ae.stat(e),s=K.basename(e),o=B();if(r.isDirectory()){let a=await ae.readdir(e),c=[];for(let p of a){if(p.startsWith("."))continue;let g=await ne(K.join(e,p),t);c.push(g)}return{name:s,id:o,size:0,children:c,type:"folder"}}else{let a=T(s);return t.set(o,{path:e,name:s,size:r.size,mediaType:a}),{name:s,id:o,size:r.size,children:[],type:"file",mediaType:a}}}class Y{uploads=new Map;isTty=process.stdout.isTTY;linesPrinted=0;addUpload(e,t,r){if(this.uploads.set(e,{name:t,size:r,uploadedBytes:0}),this.isTty)console.log(`${t.padEnd(30)} [${"░".repeat(20)}] 0%`),this.linesPrinted++,console.log(""),this.linesPrinted++}updateProgress(e,t){let r=this.uploads.get(e);if(!r)return;if(r.uploadedBytes=t,this.isTty){process.stdout.write("\x1B["+this.linesPrinted+"A"),this.linesPrinted=0;for(let s of this.uploads.values()){let o=s.size>0?Math.min(Math.round(s.uploadedBytes/s.size*100),100):100,a=20,c=Math.round(o/100*20),p="█".repeat(c)+"░".repeat(20-c);console.log(`${s.name.padEnd(30)} [${p}] ${o}%`),this.linesPrinted++,console.log(""),this.linesPrinted++}}else{let s=r.size>0?Math.min(Math.round(t/r.size*100),100):100;if(s===100||t===0||s%25===0)console.log(`Uploading ${r.name}: ${s}%`)}}}async function X(e,t,r,s){let a=Z.statSync(t).size,c=new URL(e),p=c.protocol==="https:",g=p?Se:we,l={method:"PUT",hostname:c.hostname,port:c.port||(p?443:80),path:c.pathname+c.search,headers:{"Content-Type":r,"Content-Length":a.toString()}};return new Promise((n,i)=>{let f=g.request(l,(d)=>{if(d.resume(),d.statusCode&&d.statusCode>=200&&d.statusCode<300)n();else i(Error(`Failed to upload to S3: ${d.statusCode} ${d.statusMessage}`))});f.on("error",(d)=>{i(d)});let u=Z.createReadStream(t),y=0;u.on("data",(d)=>{y+=d.length,s(y),f.write(d)}),u.on("end",()=>{f.end()}),u.on("error",(d)=>{f.destroy(),i(d)})})}async function ie(e,t){if(!e)console.error("Error: Local file/folder path is required."),process.exit(1);if(!t)console.error("Error: Parent ID (-p/--parent) is required."),process.exit(1);let r=K.resolve(e);if(!Z.existsSync(r))console.error(`Error: Local path "${r}" does not exist.`),process.exit(1);let s=k();try{let o=await s.api.folders[":folderId"].$get({param:{folderId:t}});if(!o.ok){let m=await o.json().catch(()=>({error:"Unknown error"}));console.error(`Error fetching parent folder details: ${m.error||"Failed"}`),process.exit(1)}let c=(await o.json()).projectId;if(!c)console.error("Error: Parent folder does not belong to any project."),process.exit(1);let p=await s.api.projects[":projectId"].$get({param:{projectId:c}});if(!p.ok){let m=await p.json().catch(()=>({error:"Unknown error"}));console.error(`Error fetching project details: ${m.error||"Failed"}`),process.exit(1)}let l=(await p.json()).teamId,n=new Map,i=await ne(r,n);console.log(`Starting upload task for ${n.size} files...`);let f=await s.api.teams[":teamId"].upload.tasks.$post({param:{teamId:l},json:{parentId:t,files:[i]}});if(!f.ok){let m=await f.json().catch(()=>({error:"Unknown error"}));console.error(`Error creating upload task: ${m.error||"Failed"}`),process.exit(1)}let{taskId:u,presignedUrls:y,createdAssets:d}=await f.json(),v=new Y;for(let m of y){let x=n.get(m.id);if(x)v.addUpload(m.id,x.name,x.size)}let P=3,$=[...y],q=[],h=async()=>{if($.length===0)return;let m=$.shift(),x=n.get(m.id);try{if(await X(m.url,x.path,x.mediaType,(fe)=>{v.updateProgress(m.id,fe)}),!(await s.api.teams[":teamId"].upload.tasks[":taskId"].$patch({param:{teamId:l,taskId:u},json:{fileId:m.fileId}})).ok)throw Error("Failed to confirm upload")}catch(j){console.error(`
5
- Failed to upload ${x.name}:`,j instanceof Error?j.message:j),await s.api.teams[":teamId"].upload.tasks[":taskId"].$patch({param:{teamId:l,taskId:u},json:{fileId:m.fileId,errorMessage:j instanceof Error?j.message:String(j)}}).catch(()=>{})}return h()};for(let m=0;m<Math.min(P,y.length);m++)q.push(h());if(await Promise.all(q),console.log(`
6
- Upload completed!`),d&&d.length>0){console.log("Uploaded asset IDs:");let m=new Set;m.add(i.id);for(let x of d)if(m.has(x.tempId))console.log(`- ${x.assetId}`)}}catch(o){console.error(`
7
- Error connecting to API server:`,o instanceof Error?o.message:o),process.exit(1)}}import ce from"node:fs";import pe from"node:path";async function le(e,t){if(!e)console.error("Error: Local file path is required."),process.exit(1);if(!t)console.error("Error: Parent ID (-p/--parent) is required."),process.exit(1);let r=pe.resolve(e);if(!ce.existsSync(r))console.error(`Error: Local path "${r}" does not exist.`),process.exit(1);let s=ce.statSync(r);if(s.isDirectory())console.error(`Error: Local path "${r}" is a directory. create-version only supports uploading single files.`),process.exit(1);let o=k();try{console.log(`Checking parent asset ${t}...`);let a=await o.api.folders[":folderId"].$get({param:{folderId:t}});if(!a.ok){let h=await a.json().catch(()=>({error:"Unknown error"}));console.error(`Error fetching parent asset details: ${h.error||"Failed"}`),process.exit(1)}let c=await a.json();if(c.type!=="file"&&c.type!=="version_stack")console.error(`Error: Parent asset must be a file or a version_stack (got "${c.type}").`),process.exit(1);let p=c.projectId;if(!p)console.error("Error: Parent asset does not belong to any project."),process.exit(1);let g=await o.api.projects[":projectId"].$get({param:{projectId:p}});if(!g.ok){let h=await g.json().catch(()=>({error:"Unknown error"}));console.error(`Error fetching project details: ${h.error||"Failed"}`),process.exit(1)}let n=(await g.json()).teamId,i=pe.basename(r),f=T(i),u={name:i,id:B(),size:s.size,children:[],type:"file",mediaType:f};console.log("Creating new version task...");let y=await o.api.teams[":teamId"].upload.tasks.$post({param:{teamId:n},json:{parentId:t,files:[u]}});if(!y.ok){let h=await y.json().catch(()=>({error:"Unknown error"}));console.error(`Error creating version task: ${h.error||"Failed"}`),process.exit(1)}let{taskId:d,presignedUrls:v,createdAssets:P}=await y.json();if(!v||v.length===0)console.error("Error: Server did not return presigned upload URLs."),process.exit(1);let $=v[0],q=new Y;q.addUpload($.id,i,s.size);try{if(await X($.url,r,f,(m)=>{q.updateProgress($.id,m)}),!(await o.api.teams[":teamId"].upload.tasks[":taskId"].$patch({param:{teamId:n,taskId:d},json:{fileId:$.fileId}})).ok)throw Error("Failed to confirm upload")}catch(h){console.error(`
8
- Failed to upload ${i}:`,h instanceof Error?h.message:h),await o.api.teams[":teamId"].upload.tasks[":taskId"].$patch({param:{teamId:n,taskId:d},json:{fileId:$.fileId,errorMessage:h instanceof Error?h.message:String(h)}}).catch(()=>{}),process.exit(1)}if(console.log(`
9
- Version upload completed!`),P&&P.length>0){console.log("Created version asset ID:");for(let h of P)if(h.tempId===u.id)console.log(`- ${h.assetId}`)}}catch(a){console.error(`
10
- Error connecting to API server:`,a instanceof Error?a.message:a),process.exit(1)}}function qe(){console.log(`
2
+ function B(e){return e.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,"")}function A(e){let t=B(e),r=0;for(let o=0;o<t.length;o++){let n=t.charCodeAt(o);if(n>=12288&&n<=40959||n>=65280&&n<=65519||n>=4352&&n<=4607||n>=44032&&n<=55215)r+=2;else r+=1}return r}function L(e,t){let r=B(t);if(A(r)<=e)return t;if(e<=3)return".".repeat(e);let n=e-3,s=0,a=0;for(let d=0;d<t.length;d++){if(t[d]==="\x1B"){let f=t.slice(d).match(/^[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/);if(f){d+=f[0].length-1;continue}}let c=t.charCodeAt(d),l=c>=12288&&c<=40959||c>=65280&&c<=65519||c>=4352&&c<=4607||c>=44032&&c<=55215?2:1;if(s+l>n){a=d;break}s+=l}let i=t.slice(0,a),p=t.includes("\x1B")?"\x1B[0m":"";return i+"..."+p}function Z(e,t){let r=A(t);if(r>=e)return t;return t+" ".repeat(e-r)}function j(e){return(t)=>{t.truncateFunc=e??void 0}}function T(e,t,r){if(t)return new V(e,r);return new G(e)}class V{out;maxWidth;hasHeaders=!1;rows=[];constructor(e,t){this.out=e;this.maxWidth=t}addHeader(e,...t){if(this.hasHeaders)return;this.hasHeaders=!0;for(let r of e)this.addField(r,...t);this.endRow()}addField(e,...t){if(this.rows.length===0)this.rows.push([]);let r=this.rows.length-1,o={text:e,truncateFunc:L};for(let n of t)n(o);this.rows[r].push(o)}endRow(){this.rows.push([])}render(){let e=this.rows.filter((n)=>n.length>0);if(e.length===0)return;let t=" ",r=e[0].length,o=this.calculateColumnWidths(e,t.length);for(let n of e){for(let s=0;s<n.length;s++){if(s>=r)break;let a=n[s];if(s>0)this.out.write(t);let i=a.text;if(a.truncateFunc)i=a.truncateFunc(o[s],a.text);if(a.paddingFunc)i=a.paddingFunc(o[s],i);else if(s<r-1)i=Z(o[s],i);if(a.colorFunc)i=a.colorFunc(i);this.out.write(i)}if(n.length>0)this.out.write(`
3
+ `)}}calculateColumnWidths(e,t){let r=e[0].length,o=Array(r).fill(0),n=Array(r).fill(0);for(let d of e)for(let c=0;c<d.length;c++){if(c>=r)break;let l=d[c],f=A(l.text);if(f>o[c])o[c]=f;if(l.truncateFunc===void 0&&f>n[c])n[c]=f}let s=()=>{let d=0;for(let c=0;c<r;c++)d+=n[c];return this.maxWidth-t*(r-1)-d},a=()=>{let d=0;for(let c=0;c<r;c++)if(n[c]>0)d++;return d},i=s();if(i>0){let d=r-a();if(d>0){let c=Math.floor(i/d);for(let l=0;l<r;l++)if(n[l]===0){let f=o[l];if(f<c)n[l]=f}}}i=s();let p=r-a();if(p>0){let d=Math.floor(i/p);for(let c=0;c<r;c++)if(n[c]===0){let l=o[c];if(l<d)n[c]=l;else if(d>0)n[c]=d}}if(i=s(),i>0)for(let d=0;d<r;d++){let c=o[d]-n[d],l=i;if(c<l)l=c;if(n[d]+=l,i-=l,i<=0)break}return n}}class G{out;currentCol=0;constructor(e){this.out=e}addHeader(){}addField(e){if(this.currentCol>0)this.out.write("\t");this.out.write(e),this.currentCol++}endRow(){this.out.write(`
4
+ `),this.currentCol=0}render(){}}var we=/^[\w!#$%&'*.^`|~+-]+$/;var xe=(e,t,r={})=>{if(!we.test(e))throw Error("Invalid cookie name");let o=`${e}=${t}`;if(e.startsWith("__Secure-")&&!r.secure)throw Error("__Secure- Cookie must have Secure attributes");if(e.startsWith("__Host-")){if(!r.secure)throw Error("__Host- Cookie must have Secure attributes");if(r.path!=="/")throw Error('__Host- Cookie must have Path attributes with "/"');if(r.domain)throw Error("__Host- Cookie must not have Domain attributes")}for(let n of["domain","path","sameSite","priority"])if(r[n]&&/[;\r\n]/.test(r[n]))throw Error(`${n} must not contain ";", "\\r", or "\\n"`);if(r&&typeof r.maxAge==="number"&&r.maxAge>=0){if(r.maxAge>34560000)throw Error("Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration.");o+=`; Max-Age=${r.maxAge|0}`}if(r.domain&&r.prefix!=="host")o+=`; Domain=${r.domain}`;if(r.path)o+=`; Path=${r.path}`;if(r.expires){if(r.expires.getTime()-Date.now()>34560000000)throw Error("Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future.");o+=`; Expires=${r.expires.toUTCString()}`}if(r.httpOnly)o+="; HttpOnly";if(r.secure)o+="; Secure";if(r.sameSite)o+=`; SameSite=${r.sameSite.charAt(0).toUpperCase()+r.sameSite.slice(1)}`;if(r.priority)o+=`; Priority=${r.priority.charAt(0).toUpperCase()+r.priority.slice(1)}`;if(r.partitioned){if(!r.secure)throw Error("Partitioned Cookie must have Secure attributes");o+="; Partitioned"}return o},K=(e,t,r)=>(t=encodeURIComponent(t),xe(e,t,r));var X=(e,t)=>(e=e.replace(/\/+$/,""),e=e+"/",t=t.replace(/^\/+/,""),e+t),R=(e,t)=>{for(let[r,o]of Object.entries(t)){let n=new RegExp("/:"+r+"(?:{[^/]+})?\\??(?=/|$)");e=e.replace(n,()=>o?`/${o}`:"")}return e},Q=(e)=>{let t=new URLSearchParams;for(let[r,o]of Object.entries(e)){if(o===void 0)continue;if(Array.isArray(o))for(let n of o){if(n===void 0)continue;t.append(r,n)}else t.set(r,o)}return t},Y=(e,t)=>{switch(t){case"ws":return e.replace(/^http/,"ws");case"http":return e.replace(/^ws/,"http")}},N=(e)=>{if(/^https?:\/\/[^\/]+?\/index(?=\?|$)/.test(e))return e.replace(/\/index(?=\?|$)/,"/");return e.replace(/\/index(?=\?|$)/,"")};function F(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function _(e,t){if(!F(e)&&!F(t))return t;let r={...e};for(let o in t){let n=t[o];if(F(r[o])&&F(n))r[o]=_(r[o],n);else r[o]=n}return r}var J=(e,t)=>new Proxy(()=>{},{get(o,n){if(typeof n!=="string"||n==="then")return;return J(e,[...t,n])},apply(o,n,s){return e({path:t,args:s})}}),ee=(e,t)=>{let r=t.toString();return r?`${e}?${r}`:e},ve=class{url;method;buildSearchParams;queryParams=void 0;pathParams={};rBody;cType=void 0;constructor(e,t,r){this.url=e,this.method=t,this.buildSearchParams=r.buildSearchParams}fetch=async(e,t)=>{if(e){if(e.query)this.queryParams=this.buildSearchParams(e.query);if(e.form){let i=new FormData;for(let[p,d]of Object.entries(e.form)){if(d===void 0)continue;if(Array.isArray(d))for(let c of d){if(c===void 0)continue;i.append(p,c)}else i.append(p,d)}this.rBody=i}if(e.json!==void 0)this.rBody=JSON.stringify(e.json),this.cType="application/json";if(e.param)this.pathParams=e.param}let r=this.method.toUpperCase(),o={...e?.header,...typeof t?.headers==="function"?await t.headers():t?.headers};if(e?.cookie){let i=[];for(let[p,d]of Object.entries(e.cookie)){if(d===void 0)continue;i.push(K(p,d))}if(i.length>0)o.Cookie=i.join("; ")}if(this.cType)o["Content-Type"]=this.cType;let n=new Headers;for(let[i,p]of Object.entries(o))if(p!==void 0)n.set(i,p);let s=this.url;if(s=N(s),s=R(s,this.pathParams),this.queryParams)s=ee(s,this.queryParams);r=this.method.toUpperCase();let a=!(r==="GET"||r==="HEAD");return(t?.fetch||fetch)(s,{body:a?this.rBody:void 0,method:r,headers:n,...t?.init})}},q=(e,t)=>J(function r(o){let n=t?.buildSearchParams??Q,s=[...o.path],a=s.slice(-3).reverse();if(a[0]==="toString"){if(a[1]==="name")return a[2]||"";return r.toString()}if(a[0]==="valueOf"){if(a[1]==="name")return a[2]||"";return r}let i="";if(/^\$/.test(a[0])){let l=s.pop();if(l)i=l.replace(/^\$/,"")}let p=s.join("/"),d=X(e,p);if(i==="url"||i==="path"){let l=d;if(o.args[0]){if(o.args[0].param)l=R(d,o.args[0].param);if(o.args[0].query)l=ee(l,n(o.args[0].query))}if(l=N(l),i==="url")return new URL(l);return l.slice(e.replace(/\/+$/,"").length).replace(/^\/?/,"/")}if(i==="ws"){let l=Y(o.args[0]?.param?R(d,o.args[0].param):d,"ws"),f=new URL(l),g=o.args[0]?.query;if(g)n(g).forEach((v,E)=>{f.searchParams.append(E,v)});return((...u)=>{if(t?.webSocket!==void 0&&typeof t.webSocket==="function")return t.webSocket(...u);return new WebSocket(...u)})(f.toString())}let c=new ve(d,i,{buildSearchParams:n});if(i){t??={};let l={...o.args[1]},f=t.headers,g=l.headers;if(f&&g)l.headers=async()=>({...typeof f==="function"?await f():f,...typeof g==="function"?await g():g});let x=_(t,l);return c.fetch(o.args[0],x)}return c},[]);function w(){let e=process.env.SHUMAI_API_KEY,t=process.env.SHUMAI_API_SERVER;if(!t)console.error("Error: SHUMAI_API_SERVER environment variable is not set."),process.exit(1);if(!e)console.error("Error: SHUMAI_API_KEY environment variable is not set. Please generate a token in the Settings -> Developer tab."),process.exit(1);return q(t,{headers:{Authorization:`Bearer ${e}`}})}async function re(){let e=w();try{let t=await e.api.projects.$get({query:{first:"200"}});if(!t.ok){let a=await t.json().catch(()=>({error:"Unknown error"}));console.error(`Error: ${a.error||"Failed to list projects"}`),process.exit(1)}let{data:r}=await t.json();if(r.length===0){console.log("No projects found.");return}let o=process.stdout.isTTY,n=process.stdout.columns||80,s=T(process.stdout,o,n);s.addHeader(["ID","Name","Root Folder ID"]);for(let a of r)s.addField(a.id||""),s.addField(a.name||""),s.addField(a.rootFolder||""),s.endRow();s.render()}catch(t){console.error("Error connecting to API server:",t instanceof Error?t.message:t),process.exit(1)}}function Ie(e){if(e===0)return"-";let t=1024,r=["B","KB","MB","GB","TB"],o=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,o)).toFixed(2))+" "+r[o]}async function te(e){if(!e)console.error("Error: Parent ID (-p/--parent) is required."),process.exit(1);let t=w();try{let[r,o]=await Promise.all([t.api.folders[":folderId"].children.$get({param:{folderId:e},query:{assetType:"folder",first:"200"}}),t.api.folders[":folderId"].children.$get({param:{folderId:e},query:{assetType:"file",first:"200"}})]);if(!r.ok){let f=await r.json().catch(()=>({error:"Unknown error"}));console.error(`Error: ${f.error||"Failed to list folders"}`),process.exit(1)}if(!o.ok){let f=await o.json().catch(()=>({error:"Unknown error"}));console.error(`Error: ${f.error||"Failed to list files"}`),process.exit(1)}let n=await r.json(),s=await o.json(),a=n.data||[],i=s.data||[],p=[...a.map((f)=>({...f,typeDisplay:"folder"})),...i.map((f)=>({...f,typeDisplay:"file"}))];if(p.length===0){console.log("No assets found in this folder.");return}let d=process.stdout.isTTY,c=process.stdout.columns||80,l=T(process.stdout,d,c);l.addHeader(["ID","Name","Type","Size"]);for(let f of p)l.addField(f.id||"",j(null)),l.addField(f.name||""),l.addField(f.typeDisplay,j(null)),l.addField(f.typeDisplay==="folder"?"-":Ie(f.sizeByte||0),j(null)),l.endRow();l.render()}catch(r){console.error("Error connecting to API server:",r instanceof Error?r.message:r),process.exit(1)}}async function oe(e,t){if(!e)console.error("Error: Folder name is required."),process.exit(1);if(!t)console.error("Error: Parent ID (-p/--parent) is required."),process.exit(1);let r=w();try{let o=await r.api.folders.$post({json:{name:e,parentId:t}});if(!o.ok){let s=await o.json().catch(()=>({error:"Unknown error"}));console.error(`Error: ${s.error||"Failed to create folder"}`),process.exit(1)}let n=await o.json();console.log(`Created folder with ID: ${n.id}`)}catch(o){console.error("Error connecting to API server:",o instanceof Error?o.message:o),process.exit(1)}}import W from"node:fs";import ae from"node:fs/promises";import je from"node:http";import Te from"node:https";import D from"node:path";import U from"node:crypto";var se="0123456789ABCDEFGHJKMNPQRSTVWXYZ",S=32;var Ee=16,ie=10,ne=281474976710655;var C;(function(e){e.Base32IncorrectEncoding="B32_ENC_INVALID",e.DecodeTimeInvalidCharacter="DEC_TIME_CHAR",e.DecodeTimeValueMalformed="DEC_TIME_MALFORMED",e.EncodeTimeNegative="ENC_TIME_NEG",e.EncodeTimeSizeExceeded="ENC_TIME_SIZE_EXCEED",e.EncodeTimeValueMalformed="ENC_TIME_MALFORMED",e.PRNGDetectFailure="PRNG_DETECT",e.ULIDInvalid="ULID_INVALID",e.Unexpected="UNEXPECTED",e.UUIDInvalid="UUID_INVALID"})(C||(C={}));class P extends Error{constructor(e,t){super(`${t} (${e})`);this.name="ULIDError",this.code=e}}function be(e){let t=Math.floor(e()*S)%S;return se.charAt(t)}function $e(e){let t=Ce(),r=t&&(t.crypto||t.msCrypto)||(typeof U<"u"?U:null);if(typeof r?.getRandomValues==="function")return()=>{let o=new Uint8Array(1);return r.getRandomValues(o),o[0]/256};else if(typeof r?.randomBytes==="function")return()=>r.randomBytes(1).readUInt8()/256;else if(U?.randomBytes)return()=>U.randomBytes(1).readUInt8()/256;throw new P(C.PRNGDetectFailure,"Failed to find a reliable PRNG")}function Ce(){if(Ae())return self;if(typeof window<"u")return window;if(typeof global<"u")return global;if(typeof globalThis<"u")return globalThis;return null}function Pe(e,t){let r="";for(;e>0;e--)r=be(t)+r;return r}function ke(e,t=ie){if(isNaN(e))throw new P(C.EncodeTimeValueMalformed,`Time must be a number: ${e}`);else if(e>ne)throw new P(C.EncodeTimeSizeExceeded,`Cannot encode a time larger than ${ne}: ${e}`);else if(e<0)throw new P(C.EncodeTimeNegative,`Time must be positive: ${e}`);else if(Number.isInteger(e)===!1)throw new P(C.EncodeTimeValueMalformed,`Time must be an integer: ${e}`);let r,o="";for(let n=t;n>0;n--)r=e%S,o=se.charAt(r)+o,e=(e-r)/S;return o}function Ae(){return typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope}function O(e,t){let r=t||$e(),o=!e||isNaN(e)?Date.now():e;return ke(o,ie)+Pe(Ee,r)}function z(e){let t=D.extname(e).toLowerCase();return{".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".webp":"image/webp",".mp4":"video/mp4",".mkv":"video/x-matroska",".mov":"video/quicktime",".avi":"video/x-msvideo",".webm":"video/webm",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".txt":"text/plain",".md":"text/markdown",".markdown":"text/markdown",".json":"application/json",".pdf":"application/pdf",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip"}[t]||"application/octet-stream"}async function ce(e,t){let r=await ae.stat(e),o=D.basename(e),n=O();if(r.isDirectory()){let s=await ae.readdir(e),a=[];for(let i of s){if(i.startsWith("."))continue;let p=await ce(D.join(e,i),t);a.push(p)}return{name:o,id:n,size:0,children:a,type:"folder"}}else{let s=z(o);return t.set(n,{path:e,name:o,size:r.size,mediaType:s}),{name:o,id:n,size:r.size,children:[],type:"file",mediaType:s}}}class M{uploads=new Map;isTty=process.stdout.isTTY;linesPrinted=0;addUpload(e,t,r){if(this.uploads.set(e,{name:t,size:r,uploadedBytes:0}),this.isTty)console.log(`${t.padEnd(30)} [${"░".repeat(20)}] 0%`),this.linesPrinted++,console.log(""),this.linesPrinted++}updateProgress(e,t){let r=this.uploads.get(e);if(!r)return;if(r.uploadedBytes=t,this.isTty){process.stdout.write("\x1B["+this.linesPrinted+"A"),this.linesPrinted=0;for(let o of this.uploads.values()){let n=o.size>0?Math.min(Math.round(o.uploadedBytes/o.size*100),100):100,s=20,a=Math.round(n/100*20),i="█".repeat(a)+"░".repeat(20-a);console.log(`${o.name.padEnd(30)} [${i}] ${n}%`),this.linesPrinted++,console.log(""),this.linesPrinted++}}else{let o=r.size>0?Math.min(Math.round(t/r.size*100),100):100;if(o===100||t===0||o%25===0)console.log(`Uploading ${r.name}: ${o}%`)}}}async function H(e,t,r,o){let s=W.statSync(t).size,a=new URL(e),i=a.protocol==="https:",p=i?Te:je,d={method:"PUT",hostname:a.hostname,port:a.port||(i?443:80),path:a.pathname+a.search,headers:{"Content-Type":r,"Content-Length":s.toString()}};return new Promise((c,l)=>{let f=p.request(d,(u)=>{if(u.resume(),u.statusCode&&u.statusCode>=200&&u.statusCode<300)c();else l(Error(`Failed to upload to S3: ${u.statusCode} ${u.statusMessage}`))});f.on("error",(u)=>{l(u)});let g=W.createReadStream(t),x=0;g.on("data",(u)=>{x+=u.length,o(x),f.write(u)}),g.on("end",()=>{f.end()}),g.on("error",(u)=>{f.destroy(),l(u)})})}async function le(e,t){if(!e)console.error("Error: Local file/folder path is required."),process.exit(1);if(!t)console.error("Error: Parent ID (-p/--parent) is required."),process.exit(1);let r=D.resolve(e);if(!W.existsSync(r))console.error(`Error: Local path "${r}" does not exist.`),process.exit(1);let o=w();try{let n=await o.api.folders[":folderId"].$get({param:{folderId:t}});if(!n.ok){let m=await n.json().catch(()=>({error:"Unknown error"}));console.error(`Error fetching parent folder details: ${m.error||"Failed"}`),process.exit(1)}let a=(await n.json()).projectId;if(!a)console.error("Error: Parent folder does not belong to any project."),process.exit(1);let i=await o.api.projects[":projectId"].$get({param:{projectId:a}});if(!i.ok){let m=await i.json().catch(()=>({error:"Unknown error"}));console.error(`Error fetching project details: ${m.error||"Failed"}`),process.exit(1)}let d=(await i.json()).teamId,c=new Map,l=await ce(r,c);console.log(`Starting upload task for ${c.size} files...`);let f=await o.api.teams[":teamId"].upload.tasks.$post({param:{teamId:d},json:{parentId:t,files:[l]}});if(!f.ok){let m=await f.json().catch(()=>({error:"Unknown error"}));console.error(`Error creating upload task: ${m.error||"Failed"}`),process.exit(1)}let{taskId:g,presignedUrls:x,createdAssets:u}=await f.json(),v=new M;for(let m of x){let y=c.get(m.id);if(y)v.addUpload(m.id,y.name,y.size)}let E=3,I=[...x],k=[],h=async()=>{if(I.length===0)return;let m=I.shift(),y=c.get(m.id);try{if(await H(m.url,y.path,y.mediaType,(ge)=>{v.updateProgress(m.id,ge)}),!(await o.api.teams[":teamId"].upload.tasks[":taskId"].$patch({param:{teamId:d,taskId:g},json:{fileId:m.fileId}})).ok)throw Error("Failed to confirm upload")}catch(b){console.error(`
5
+ Failed to upload ${y.name}:`,b instanceof Error?b.message:b),await o.api.teams[":teamId"].upload.tasks[":taskId"].$patch({param:{teamId:d,taskId:g},json:{fileId:m.fileId,errorMessage:b instanceof Error?b.message:String(b)}}).catch(()=>{})}return h()};for(let m=0;m<Math.min(E,x.length);m++)k.push(h());if(await Promise.all(k),console.log(`
6
+ Upload completed!`),u&&u.length>0){console.log("Uploaded asset IDs:");let m=new Set;m.add(l.id);for(let y of u)if(m.has(y.tempId))console.log(`- ${y.assetId}`)}}catch(n){console.error(`
7
+ Error connecting to API server:`,n instanceof Error?n.message:n),process.exit(1)}}import de from"node:fs";import fe from"node:path";async function pe(e,t){if(!e)console.error("Error: Local file path is required."),process.exit(1);if(!t)console.error("Error: Parent ID (-p/--parent) is required."),process.exit(1);let r=fe.resolve(e);if(!de.existsSync(r))console.error(`Error: Local path "${r}" does not exist.`),process.exit(1);let o=de.statSync(r);if(o.isDirectory())console.error(`Error: Local path "${r}" is a directory. create-version only supports uploading single files.`),process.exit(1);let n=w();try{console.log(`Checking parent asset ${t}...`);let s=await n.api.folders[":folderId"].$get({param:{folderId:t}});if(!s.ok){let h=await s.json().catch(()=>({error:"Unknown error"}));console.error(`Error fetching parent asset details: ${h.error||"Failed"}`),process.exit(1)}let a=await s.json();if(a.type!=="file"&&a.type!=="version_stack")console.error(`Error: Parent asset must be a file or a version_stack (got "${a.type}").`),process.exit(1);let i=a.projectId;if(!i)console.error("Error: Parent asset does not belong to any project."),process.exit(1);let p=await n.api.projects[":projectId"].$get({param:{projectId:i}});if(!p.ok){let h=await p.json().catch(()=>({error:"Unknown error"}));console.error(`Error fetching project details: ${h.error||"Failed"}`),process.exit(1)}let c=(await p.json()).teamId,l=fe.basename(r),f=z(l),g={name:l,id:O(),size:o.size,children:[],type:"file",mediaType:f};console.log("Creating new version task...");let x=await n.api.teams[":teamId"].upload.tasks.$post({param:{teamId:c},json:{parentId:t,files:[g]}});if(!x.ok){let h=await x.json().catch(()=>({error:"Unknown error"}));console.error(`Error creating version task: ${h.error||"Failed"}`),process.exit(1)}let{taskId:u,presignedUrls:v,createdAssets:E}=await x.json();if(!v||v.length===0)console.error("Error: Server did not return presigned upload URLs."),process.exit(1);let I=v[0],k=new M;k.addUpload(I.id,l,o.size);try{if(await H(I.url,r,f,(m)=>{k.updateProgress(I.id,m)}),!(await n.api.teams[":teamId"].upload.tasks[":taskId"].$patch({param:{teamId:c,taskId:u},json:{fileId:I.fileId}})).ok)throw Error("Failed to confirm upload")}catch(h){console.error(`
8
+ Failed to upload ${l}:`,h instanceof Error?h.message:h),await n.api.teams[":teamId"].upload.tasks[":taskId"].$patch({param:{teamId:c,taskId:u},json:{fileId:I.fileId,errorMessage:h instanceof Error?h.message:String(h)}}).catch(()=>{}),process.exit(1)}if(console.log(`
9
+ Version upload completed!`),E&&E.length>0){console.log("Created version asset ID:");for(let h of E)if(h.tempId===g.id)console.log(`- ${h.assetId}`)}}catch(s){console.error(`
10
+ Error connecting to API server:`,s instanceof Error?s.message:s),process.exit(1)}}async function ue(e,t){if(!e)console.error("Error: Asset ID is required. Usage: shumai-cli rename <assetId> <newName>"),process.exit(1);if(!t)console.error("Error: New name is required. Usage: shumai-cli rename <assetId> <newName>"),process.exit(1);let r=w();try{let o=await r.api.folders[":folderId"].$get({param:{folderId:e}});if(!o.ok){let i=await o.json().catch(()=>({error:"Asset not found"}));console.error(`Error: ${i.error||"Asset not found"}`),process.exit(1)}let a=(await o.json()).type==="folder"?await r.api.folders[":folderId"].$put({param:{folderId:e},json:{name:t}}):await r.api.files[":fileId"].$put({param:{fileId:e},json:{name:t}});if(!a.ok){let i=await a.json().catch(()=>({error:"Failed to rename asset"}));console.error(`Error: ${i.error||"Failed to rename asset"}`),process.exit(1)}console.log(`Renamed asset ${e} to "${t}"`)}catch(o){console.error("Error connecting to API server:",o instanceof Error?o.message:o),process.exit(1)}}async function me(e,t){if(!e||e.length===0)console.error("Error: At least one asset ID is required. Usage: shumai-cli move <assetId...> -p <parentId>"),process.exit(1);if(!t)console.error("Error: Option -p/--parent <parentId> is required."),process.exit(1);let r=w();try{let o=await r.api.folders[":folderId"].$get({param:{folderId:t}});if(!o.ok){let i=await o.json().catch(()=>({error:"Parent folder not found"}));console.error(`Error: ${i.error||"Parent folder not found"}`),process.exit(1)}let s=(await o.json()).projectId;if(!s)console.error("Error: Destination parent folder is not associated with a project."),process.exit(1);let a=await r.api.projects[":projectId"].reparent.$post({param:{projectId:s},json:{assetIds:e,newParentId:t}});if(!a.ok){let i=await a.json().catch(()=>({error:"Failed to move assets"}));console.error(`Error: ${i.error||"Failed to move assets"}`),process.exit(1)}console.log(`Moved ${e.length} asset(s) to parent ${t}`)}catch(o){console.error("Error connecting to API server:",o instanceof Error?o.message:o),process.exit(1)}}async function he(e){if(!(process.env.SHUMAI_ALLOW_DELETE==="true"||process.env.SHUMAI_ALLOW_DELETE==="1"))console.error("Error: Asset deletion is disabled in this environment."),process.exit(1);if(!e||e.length===0)console.error("Error: Asset ID is required. Usage: shumai-cli delete <assetId>"),process.exit(1);if(e.length>1)console.error("Error: Can only delete one asset at a time."),process.exit(1);let r=e[0],o=w();try{let n=await o.api.folders[":folderId"].$get({param:{folderId:r}});if(!n.ok){let p=await n.json().catch(()=>({error:"Asset not found"}));console.error(`Error: ${p.error||"Asset not found"}`),process.exit(1)}let i=(await n.json()).type==="folder"?await o.api.folders.$delete({json:{ids:[r]}}):await o.api.files.$delete({json:{ids:[r]}});if(!i.ok){let p=await i.json().catch(()=>({error:"Failed to delete asset"}));console.error(`Error: ${p.error||"Failed to delete asset"}`),process.exit(1)}console.log(`Deleted asset ${r}`)}catch(n){console.error("Error connecting to API server:",n instanceof Error?n.message:n),process.exit(1)}}function Fe(){console.log(`
11
11
  Usage: shumai-cli <command> [arguments] [options]
12
12
 
13
13
  Commands:
@@ -16,8 +16,11 @@ Commands:
16
16
  mkdir <name> -p <parentId> Create a new folder in a parent folder
17
17
  upload <path> -p <parentId> Upload a local file or folder to a parent folder
18
18
  create-version <path> -p <id> Create a new version of an existing file or version stack
19
+ rename <assetId> <newName> Rename an existing file or folder
20
+ move <assetIds...> -p <target> Move one or more assets to a destination parent folder (alias: mv)
21
+ delete <assetId> Delete a single file or folder (alias: rm)
19
22
 
20
23
  Options:
21
- -p, --parent <id> The parent folder/asset ID (required for ls, mkdir, upload, create-version)
24
+ -p, --parent <id> The parent folder/asset ID (required for ls, mkdir, upload, create-version, move)
22
25
  -h, --help Show help details
23
- `)}async function Fe(){let e=process.argv.slice(2);if(e.length===0||e.includes("-h")||e.includes("--help"))qe(),process.exit(0);let t=e[0],r="",s=e.findIndex((a)=>a==="-p"||a==="--parent");if(s!==-1&&s+1<e.length)r=e[s+1];let o=[];for(let a=0;a<e.length;a++)if(e[a]==="-p"||e[a]==="--parent")a++;else o.push(e[a]);if(t==="project"&&o[1]==="ls")await L();else if(t==="ls"){if(!r)console.error("Error: Option -p/--parent <parentId> is required."),process.exit(1);await ee(r)}else if(t==="mkdir"){let a=o[1];if(!a)console.error("Error: Folder name is required. Usage: shumai-cli mkdir <folderName> -p <parentId>"),process.exit(1);if(!r)console.error("Error: Option -p/--parent <parentId> is required."),process.exit(1);await re(a,r)}else if(t==="upload"){let a=o[1];if(!a)console.error("Error: File/folder path is required. Usage: shumai-cli upload <localPath> -p <parentId>"),process.exit(1);if(!r)console.error("Error: Option -p/--parent <parentId> is required."),process.exit(1);await ie(a,r)}else if(t==="create-version"){let a=o[1];if(!a)console.error("Error: Local file path is required. Usage: shumai-cli create-version <localPath> -p <parentAssetId>"),process.exit(1);if(!r)console.error("Error: Option -p/--parent <parentAssetId> is required."),process.exit(1);await le(a,r)}else console.error(`Error: Unknown command "${t}". Run "shumai-cli --help" for usage.`),process.exit(1)}Fe().catch((e)=>{console.error("Unexpected error:",e),process.exit(1)});
26
+ `)}async function Re(){let e=process.argv.slice(2);if(e.length===0||e.includes("-h")||e.includes("--help"))Fe(),process.exit(0);let t=e[0],r="",o=e.findIndex((s)=>s==="-p"||s==="--parent");if(o!==-1&&o+1<e.length)r=e[o+1];let n=[];for(let s=0;s<e.length;s++)if(e[s]==="-p"||e[s]==="--parent")s++;else n.push(e[s]);if(t==="project"&&n[1]==="ls")await re();else if(t==="ls"){if(!r)console.error("Error: Option -p/--parent <parentId> is required."),process.exit(1);await te(r)}else if(t==="mkdir"){let s=n[1];if(!s)console.error("Error: Folder name is required. Usage: shumai-cli mkdir <folderName> -p <parentId>"),process.exit(1);if(!r)console.error("Error: Option -p/--parent <parentId> is required."),process.exit(1);await oe(s,r)}else if(t==="upload"){let s=n[1];if(!s)console.error("Error: File/folder path is required. Usage: shumai-cli upload <localPath> -p <parentId>"),process.exit(1);if(!r)console.error("Error: Option -p/--parent <parentId> is required."),process.exit(1);await le(s,r)}else if(t==="create-version"){let s=n[1];if(!s)console.error("Error: Local file path is required. Usage: shumai-cli create-version <localPath> -p <parentAssetId>"),process.exit(1);if(!r)console.error("Error: Option -p/--parent <parentAssetId> is required."),process.exit(1);await pe(s,r)}else if(t==="rename"){let s=n[1],a=n[2];if(!s||!a)console.error("Error: Asset ID and new name are required. Usage: shumai-cli rename <assetId> <newName>"),process.exit(1);await ue(s,a)}else if(t==="move"||t==="mv"){let s=n.slice(1);if(s.length===0)console.error("Error: At least one asset ID is required. Usage: shumai-cli move <assetId...> -p <parentId>"),process.exit(1);if(!r)console.error("Error: Option -p/--parent <parentId> is required."),process.exit(1);await me(s,r)}else if(t==="delete"||t==="rm"){let s=n.slice(1);if(s.length===0)console.error("Error: Asset ID is required. Usage: shumai-cli delete <assetId>"),process.exit(1);await he(s)}else console.error(`Error: Unknown command "${t}". Run "shumai-cli --help" for usage.`),process.exit(1)}Re().catch((e)=>{console.error("Unexpected error:",e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shumai-one/shumai-cli",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "Command line interface for the shumai media workspace",
5
5
  "type": "module",
6
6
  "bin": {