@shumai-one/shumai-cli 0.0.10

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 +23 -0
  2. package/package.json +16 -0
@@ -0,0 +1,23 @@
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",".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(`
11
+ Usage: shumai-cli <command> [arguments] [options]
12
+
13
+ Commands:
14
+ project ls List all projects (returns id, name, root folder id)
15
+ ls -p <parentId> List direct children of a parent folder (returns id, name, type, size)
16
+ mkdir <name> -p <parentId> Create a new folder in a parent folder
17
+ upload <path> -p <parentId> Upload a local file or folder to a parent folder
18
+ create-version <path> -p <id> Create a new version of an existing file or version stack
19
+
20
+ Options:
21
+ -p, --parent <id> The parent folder/asset ID (required for ls, mkdir, upload, create-version)
22
+ -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)});
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@shumai-one/shumai-cli",
3
+ "version": "0.0.10",
4
+ "description": "Command line interface for the shumai media workspace",
5
+ "type": "module",
6
+ "bin": {
7
+ "shumai-cli": "./bin/shumai-cli.js"
8
+ },
9
+ "files": [
10
+ "bin"
11
+ ],
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/shumaiOne/shumai.git"
15
+ }
16
+ }