s3it 1.1.1 → 1.2.0

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/dist/index.js +7 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import{basename as h,extname as u}from"node:path";import{randomUUID as n,createHash as f,createHmac as z}from"node:crypto";import{promises as k}from"node:fs";var B=process.env.S3_ENDPOINT||"https://s3.reily.app",M=process.env.S3_BUCKET||"public",A=process.env.S3_ACCESS_KEY||"bhEJaGR0UGgmZtxEi2yY",Y=process.env.S3_SECRET_KEY||"lE1fn0FdAAhQwFLnumJt0th0Q2j684h4v8EIQdzy",O=process.env.S3_REGION||"auto",p=104857600,R=104857600;function i(j,V,w,J){let X=z("sha256",`AWS4${j}`).update(V).digest(),W=z("sha256",X).update(w).digest(),$=z("sha256",W).update(J).digest();return z("sha256",$).update("aws4_request").digest()}function D(j,V,w,J,X,W,$){let F=new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),L=F.slice(0,8),U=V.pathname,b=new URLSearchParams(V.search),C=Array.from(b.entries()).sort((x,Z)=>x[0].localeCompare(Z[0])).map(([x,Z])=>`${encodeURIComponent(x)}=${encodeURIComponent(Z)}`).join("&"),K=f("sha256").update(typeof J==="string"?J:J).digest("hex"),q={};for(let[x,Z]of Object.entries(w))q[x.toLowerCase()]=Z;q.host=V.host,q["x-amz-date"]=F,q["x-amz-content-sha256"]=K;let H=Object.keys(q).sort(),_=H.map((x)=>`${x}:${q[x].trim()}`).join(`
2
+ import{basename as u,extname as p}from"node:path";import{randomUUID as i,createHash as I,createHmac as D}from"node:crypto";import{promises as H}from"node:fs";var z=process.env.S3_ENDPOINT||"https://s3.reily.app",A=process.env.S3_BUCKET||"public",U=process.env.S3_ACCESS_KEY||"bhEJaGR0UGgmZtxEi2yY",v=process.env.S3_SECRET_KEY||"lE1fn0FdAAhQwFLnumJt0th0Q2j684h4v8EIQdzy",k=process.env.S3_REGION||"auto",n=104857600,N=104857600;function l(j,J,W,X){let w=D("sha256",`AWS4${j}`).update(J).digest(),$=D("sha256",w).update(W).digest(),Q=D("sha256",$).update(X).digest();return D("sha256",Q).update("aws4_request").digest()}function b(j,J,W,X,w,$,Q){let Z=new Date().toISOString().replace(/[:-]|\.\d{3}/g,""),L=Z.slice(0,8),C=J.pathname,B=new URLSearchParams(J.search),K=Array.from(B.entries()).sort((V,q)=>V[0].localeCompare(q[0])).map(([V,q])=>`${encodeURIComponent(V)}=${encodeURIComponent(q)}`).join("&"),O=I("sha256").update(typeof X==="string"?X:X).digest("hex"),F={};for(let[V,q]of Object.entries(W))F[V.toLowerCase()]=q;F.host=J.host,F["x-amz-date"]=Z,F["x-amz-content-sha256"]=O;let R=Object.keys(F).sort(),c=R.map((V)=>`${V}:${F[V].trim()}`).join(`
3
3
  `)+`
4
- `,N=H.join(";"),E=[j,U,C,_,N,K].join(`
5
- `),T="AWS4-HMAC-SHA256",y=`${L}/${$}/s3/aws4_request`,P=[T,F,y,f("sha256").update(E).digest("hex")].join(`
6
- `),c=i(W,L,$,"s3"),m=z("sha256",c).update(P).digest("hex"),S=`${T} Credential=${X}/${y}, SignedHeaders=${N}, Signature=${m}`,v={};for(let[x,Z]of Object.entries(w))v[x]=Z;return v.Host=V.host,v["X-Amz-Date"]=F,v["X-Amz-Content-Sha256"]=K,v.Authorization=S,v}function o(j){let V=u(j).toLowerCase();return{".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".bmp":"image/bmp",".ico":"image/x-icon",".tiff":"image/tiff",".tif":"image/tiff",".avif":"image/avif",".heic":"image/heic",".heif":"image/heif",".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".html":"text/html",".htm":"text/html",".css":"text/css",".js":"text/javascript",".mjs":"text/javascript",".json":"application/json",".xml":"application/xml",".csv":"text/csv",".md":"text/markdown",".yaml":"text/yaml",".yml":"text/yaml",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".tgz":"application/gzip",".7z":"application/x-7z-compressed",".rar":"application/vnd.rar",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".m4a":"audio/mp4",".flac":"audio/flac",".mp4":"video/mp4",".avi":"video/x-msvideo",".mov":"video/quicktime",".wmv":"video/x-ms-wmv",".webm":"video/webm",".mkv":"video/x-matroska",".ts":"text/typescript",".tsx":"text/typescript",".jsx":"text/javascript",".py":"text/x-python",".java":"text/x-java",".c":"text/x-c",".cpp":"text/x-c++",".rs":"text/x-rust",".go":"text/x-go",".rb":"text/x-ruby",".php":"text/x-php",".sh":"text/x-shellscript",".sql":"text/x-sql",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".wasm":"application/wasm"}[V]||"application/octet-stream"}async function l(j,V){let w=new URL(`${B}/${M}/${j}?uploads`),J=D("POST",w,{"Content-Type":V},"",A,Y,O),X=await fetch(w.toString(),{method:"POST",headers:J});if(!X.ok)throw Error(`Failed to initiate multipart upload: ${X.status}`);let $=(await X.text()).match(/<UploadId>(.+?)<\/UploadId>/);if(!$)throw Error("Failed to parse UploadId");return $[1]}async function d(j,V,w,J){let X=new URL(`${B}/${M}/${j}?partNumber=${w}&uploadId=${encodeURIComponent(V)}`),W=D("PUT",X,{"Content-Length":String(J.length)},J,A,Y,O),$=await fetch(X.toString(),{method:"PUT",headers:W,body:J});if(!$.ok)throw Error(`Failed to upload part ${w}: ${$.status}`);let Q=$.headers.get("ETag");if(!Q)throw Error(`No ETag for part ${w}`);return Q}async function s(j,V,w){let J=new URL(`${B}/${M}/${j}?uploadId=${encodeURIComponent(V)}`),W=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${w.map((G)=>`<Part><PartNumber>${G.partNumber}</PartNumber><ETag>${G.etag}</ETag></Part>`).join("")}</CompleteMultipartUpload>`,$=D("POST",J,{"Content-Type":"application/xml"},W,A,Y,O),Q=await fetch(J.toString(),{method:"POST",headers:$,body:W});if(!Q.ok)throw Error(`Failed to complete multipart upload: ${Q.status}`)}async function r(j,V){let w=new URL(`${B}/${M}/${j}?uploadId=${encodeURIComponent(V)}`),J=D("DELETE",w,{},"",A,Y,O);await fetch(w.toString(),{method:"DELETE",headers:J})}async function t(j,V,w){let J=new URL(`${B}/${M}/${j}`),X=D("PUT",J,{"Content-Type":w,"Content-Length":String(V.length)},V,A,Y,O),W=await fetch(J.toString(),{method:"PUT",headers:X,body:V});if(!W.ok)throw Error(`Upload failed: ${W.status}`)}async function a(j,V,w){let J=await k.open(j,"r");try{let X=Buffer.alloc(w),{bytesRead:W}=await J.read(X,0,w,V);return X.subarray(0,W)}finally{await J.close()}}async function e(j){try{await k.access(j)}catch{throw Error(`File not found: ${j}`)}let w=(await k.stat(j)).size,J=n(),X=h(j),W=`${J}/${X}`,$=o(j);if(w<=p){let Q=await k.readFile(j);await t(W,Q,$)}else{process.stderr.write(`Uploading ${(w/1024/1024).toFixed(1)}MB...
7
- `);let Q=await l(W,$),G=[];try{let F=Math.ceil(w/R);for(let L=1;L<=F;L++){let U=(L-1)*R,b=Math.min(R,w-U);process.stderr.write(`Part ${L}/${F}
8
- `);let I=await a(j,U,b),C=await d(W,Q,L,I);G.push({partNumber:L,etag:C})}await s(W,Q,G)}catch(F){throw await r(W,Q),F}}return`${B}/${M}/${W}`}var g=process.argv[2];if(!g)console.error("Usage: s3it <file>"),process.exit(1);e(g).then((j)=>console.log(j)).catch((j)=>{console.error(j.message),process.exit(1)});
4
+ `,T=R.join(";"),E=[j,C,K,c,T,O].join(`
5
+ `),y="AWS4-HMAC-SHA256",f=`${L}/${Q}/s3/aws4_request`,P=[y,Z,f,I("sha256").update(E).digest("hex")].join(`
6
+ `),m=l($,L,Q,"s3"),S=D("sha256",m).update(P).digest("hex"),h=`${y} Credential=${w}/${f}, SignedHeaders=${T}, Signature=${S}`,M={};for(let[V,q]of Object.entries(W))M[V]=q;return M.Host=J.host,M["X-Amz-Date"]=Z,M["X-Amz-Content-Sha256"]=O,M.Authorization=h,M}function o(j){let J=p(j).toLowerCase();return{".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".bmp":"image/bmp",".ico":"image/x-icon",".tiff":"image/tiff",".tif":"image/tiff",".avif":"image/avif",".heic":"image/heic",".heif":"image/heif",".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".html":"text/html",".htm":"text/html",".css":"text/css",".js":"text/javascript",".mjs":"text/javascript",".json":"application/json",".xml":"application/xml",".csv":"text/csv",".md":"text/markdown",".yaml":"text/yaml",".yml":"text/yaml",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".tgz":"application/gzip",".7z":"application/x-7z-compressed",".rar":"application/vnd.rar",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".m4a":"audio/mp4",".flac":"audio/flac",".mp4":"video/mp4",".avi":"video/x-msvideo",".mov":"video/quicktime",".wmv":"video/x-ms-wmv",".webm":"video/webm",".mkv":"video/x-matroska",".ts":"text/typescript",".tsx":"text/typescript",".jsx":"text/javascript",".py":"text/x-python",".java":"text/x-java",".c":"text/x-c",".cpp":"text/x-c++",".rs":"text/x-rust",".go":"text/x-go",".rb":"text/x-ruby",".php":"text/x-php",".sh":"text/x-shellscript",".sql":"text/x-sql",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".wasm":"application/wasm"}[J]||"application/octet-stream"}async function d(j,J){let W=new URL(`${z}/${A}/${j}?uploads`),X=b("POST",W,{"Content-Type":J},"",U,v,k),w=await fetch(W.toString(),{method:"POST",headers:X});if(!w.ok)throw Error(`Failed to initiate multipart upload: ${w.status}`);let Q=(await w.text()).match(/<UploadId>(.+?)<\/UploadId>/);if(!Q)throw Error("Failed to parse UploadId");return Q[1]}async function s(j,J,W,X){let w=new URL(`${z}/${A}/${j}?partNumber=${W}&uploadId=${encodeURIComponent(J)}`),$=b("PUT",w,{"Content-Length":String(X.length)},X,U,v,k),Q=await fetch(w.toString(),{method:"PUT",headers:$,body:X});if(!Q.ok)throw Error(`Failed to upload part ${W}: ${Q.status}`);let x=Q.headers.get("ETag");if(!x)throw Error(`No ETag for part ${W}`);return x}async function r(j,J,W){let X=new URL(`${z}/${A}/${j}?uploadId=${encodeURIComponent(J)}`),$=`<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${W.map((Y)=>`<Part><PartNumber>${Y.partNumber}</PartNumber><ETag>${Y.etag}</ETag></Part>`).join("")}</CompleteMultipartUpload>`,Q=b("POST",X,{"Content-Type":"application/xml"},$,U,v,k),x=await fetch(X.toString(),{method:"POST",headers:Q,body:$});if(!x.ok)throw Error(`Failed to complete multipart upload: ${x.status}`);return g(x)}async function t(j,J){let W=new URL(`${z}/${A}/${j}?uploadId=${encodeURIComponent(J)}`),X=b("DELETE",W,{},"",U,v,k);await fetch(W.toString(),{method:"DELETE",headers:X})}function g(j){let J=j.headers.get("x-amz-version-id");return J&&J!=="null"?J:null}async function a(j,J,W){let X=new URL(`${z}/${A}/${j}`),w=b("PUT",X,{"Content-Type":W,"Content-Length":String(J.length)},J,U,v,k),$=await fetch(X.toString(),{method:"PUT",headers:w,body:J});if(!$.ok)throw Error(`Upload failed: ${$.status}`);return g($)}async function e(j,J,W){let X=await H.open(j,"r");try{let w=Buffer.alloc(W),{bytesRead:$}=await X.read(w,0,W,J);return w.subarray(0,$)}finally{await X.close()}}async function jj(j){try{await H.access(j)}catch{throw Error(`File not found: ${j}`)}let W=(await H.stat(j)).size,X=i(),w=u(j),$=`${X}/${w}`,Q=o(j),x;if(W<=n){let L=await H.readFile(j);x=await a($,L,Q)}else{process.stderr.write(`Uploading ${(W/1024/1024).toFixed(1)}MB...
7
+ `);let L=await d($,Q),C=[];try{let B=Math.ceil(W/N);for(let G=1;G<=B;G++){let K=(G-1)*N,O=Math.min(N,W-K);process.stderr.write(`Part ${G}/${B}
8
+ `);let F=await e(j,K,O),R=await s($,L,G,F);C.push({partNumber:G,etag:R})}x=await r($,L,C)}catch(B){throw await t($,L),B}}let Y=$.split("/").map((L)=>encodeURIComponent(L)).join("/"),Z=`${z}/${A}/${Y}`;if(!x)return process.stderr.write(`Warning: bucket versioning is off; this link can be overwritten.
9
+ `),Z;return`${Z}?versionId=${encodeURIComponent(x)}`}var _=process.argv[2];if(!_)console.error("Usage: s3it <file>"),process.exit(1);jj(_).then((j)=>console.log(j)).catch((j)=>{console.error(j.message),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "s3it",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Simple CLI to upload files to S3 and get a shareable URL",
5
5
  "main": "dist/index.js",
6
6
  "bin": {