@smoothcdn/cli 1.0.3 → 1.0.4

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/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- var ts=Object.create;var Ie=Object.defineProperty;var ss=Object.getOwnPropertyDescriptor;var os=Object.getOwnPropertyNames;var rs=Object.getPrototypeOf,ns=Object.prototype.hasOwnProperty;var is=(e,o,t,s)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of os(o))!ns.call(e,r)&&r!==t&&Ie(e,r,{get:()=>o[r],enumerable:!(s=ss(o,r))||s.enumerable});return e};var f=(e,o,t)=>(t=e!=null?ts(rs(e)):{},is(o||!e||!e.__esModule?Ie(t,"default",{value:e,enumerable:!0}):t,e));var Qt=require("commander");var ze=require("commander");var Te=f(require("axios"),1);var K=f(require("keytar"),1),de="smoothcdn",ue="cli_token";async function Oe(e){await K.default.setPassword(de,ue,e)}async function Le(){return process.env.SCDN_TOKEN||K.default.getPassword(de,ue)}async function _e(){await K.default.deletePassword(de,ue)}async function v(){let e=await Le();return Te.default.create({baseURL:"https://smoothcdn.com/api",headers:e?{Authorization:`Bearer ${e}`}:{}})}var Ve=require("@inquirer/prompts");var Z=f(require("fs"),1),Be=f(require("path"),1);function ge(e=process.cwd()){return Be.default.join(e,".scdn.json")}function Q(){return Z.default.existsSync(ge())}function w(){return Q()?JSON.parse(Z.default.readFileSync(ge(),"utf8")):{}}function P(e){Z.default.writeFileSync(ge(),JSON.stringify(e,null,2))}var Y=f(require("ora"),1),ke=require("date-fns"),Me=require("date-fns/locale"),De=(e,o)=>{let t,s;return o&&(t=o?.status||o?.code,s=o?.response?.data?.error||o?.data?.error||o?.message),`${e}${t?` [${t}]`:""}${s?` [${s}]`:""}`},d=e=>{console.log(e)},O=e=>{(0,Y.default)(e).succeed()},u=(e,o)=>{(0,Y.default)(De(e,o)).fail()},y=e=>(0,Y.default)(e).start(),h=(e,o)=>{o.succeed(e)},g=(e,o,t)=>{o.fail(De(e,t))};function he(e){return typeof e=="string"&&(e=new Date(e)),(0,ke.formatDate)(e,"dd MMMM yyyy HH:mm:ss",{locale:Me.enUS})}function xe(e,o=2){if(!e||e===0)return"0 B";let t=1024,s=o<0?0:o,r=["B","KB","MB","GB","TB"],n=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,n)).toFixed(s))+" "+r[n]}function H(e){if(e==null)return"0";let o=Math.abs(e);return o<1e3?e.toString():o<1e6?(e/1e3).toFixed(e%1e3===0?0:1)+"k":o<1e9?(e/1e6).toFixed(e%1e6===0?0:1)+"M":(e/1e9).toFixed(e%1e9===0?0:1)+"B"}var We=new ze.Command("create-version").description("Create version for next deployments").argument("[version]","Version number, e.g. 1.0.0").action(async(e="")=>{let o=await v(),t=w();if(!t){u("No .scdn.json found.");return}let s=e||t.version,r=await(0,Ve.confirm)({message:"Create version as blank (no assets will be copied from previous version automatically) ?",default:!1});if(s){let n=y(`Creating version "${s}"`);try{let a=await o.post(`/projects/${t.projectId}/versions`,{version:s,blank:r,failIfExist:!1});a.status===201?h(`Created new version "${s}"`,n):a.status===200&&h(`Version exist "${s}"`,n),e&&(t.version=e,P(t),d(".scdn.json config file updated"),O(`Using version ${e}`))}catch(a){g(`Cannot create version ${e}`,n,a)}}else u('Missing version. Please run "scdn create-version <version>" first.')});var Re=require("commander"),ee=f(require("os"),1),He=f(require("open"),1);var Xe=new Re.Command("login").description("Authenticate via browser").action(async()=>{let e=await v(),o=y("Starting login..."),t=[];try{let s=ee.default.userInfo();s.username&&t.push(s.username)}catch{}try{let s=ee.default.platform();s&&t.push(s)}catch{}try{let s=ee.default.machine();s&&t.push(s)}catch{}try{let{data:s}=await e.post("/auth/cli",{label:t.join("-")}),{key_id:r,verification_url:n}=s;await(0,He.default)(n),o.text="Waiting for authentication...";let a=null;for(;!a;){await new Promise(I=>setTimeout(I,1500));let p=await e.post("/auth/cli/poll",{keyId:r}).catch(()=>null);if(!p?.data)continue;let{status:x}=p.data;if(x!=="pending"){if(x==="expired"){g("Login session expired. Try again.",o);return}if(x==="active"){a=p.data.api_key;break}if(x==="already_active"){g("This login session is already used.",o);return}}}await Oe(a);let i=w(),c=await(await v()).get("/status");c.data&&(i.userSlug=c.data?.slug||"",c.data?.plan>=0&&i?.plan!==c.data?.plan&&(i.plan=c.data.plan),P(i)),h("Login successful!",o)}catch{g("There was an error when authorizing",o)}});var Ue=require("commander");var Je=new Ue.Command("logout").description("Remove credential data").action(async()=>{await _e(),O("Successfully logged out")});var ot=require("commander"),S=require("@inquirer/prompts"),rt=f(require("clipboardy"),1);var we=require("globby");async function D(e=[],o=[]){let t=await(0,we.globby)(e,{dot:!0});if(o.length===0)return t;let s=await(0,we.globby)(o,{dot:!0});return t.filter(r=>!s.includes(r))}var qe=["js","mjs","css","json","svg","txt","csv","xml","md"],k=["woff2","woff","ttf","otf"],M=["png","jpg","jpeg","webp","avif"],L=["wav","aiff","aif","flac","mp3","ogg","oga","m4a","aac"],te=["pdf","doc","docx","xls","xlsx","ppt","pptx","odt","ods","odp"],Ge=["json","txt","csv","xml","md","doc","docx","xls","xlsx","ppt","pptx","odt","ods","odp"],ye={0:{projects:1,assetsPerProject:50,bandwidth:1073741824,maxRequests:2e4,maxTextAssetSize:204800,maxImageAssetSize:2097152,maxAudioAssetSize:2097152,usageEventsMaxDays:3,usageEventsMaxAmount:100},1:{projects:10,assetsPerProject:1e4,bandwidth:107374182400,maxRequests:5e6,maxTextAssetSize:512e3,maxImageAssetSize:20971520,maxAudioAssetSize:52428800,usageEventsMaxDays:7,usageEventsMaxAmount:500},2:{projects:50,assetsPerProject:1e5,bandwidth:1099511627776,maxRequests:5e7,maxTextAssetSize:1048576,maxImageAssetSize:52428800,maxAudioAssetSize:104857600,usageEventsMaxDays:14,usageEventsMaxAmount:1e3}};var as=({url:e,alt:o="",critical:t=!1,width:s,height:r})=>`<img
2
+ var ss=Object.create;var Ie=Object.defineProperty;var os=Object.getOwnPropertyDescriptor;var rs=Object.getOwnPropertyNames;var ns=Object.getPrototypeOf,is=Object.prototype.hasOwnProperty;var as=(e,o,t,s)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of rs(o))!is.call(e,r)&&r!==t&&Ie(e,r,{get:()=>o[r],enumerable:!(s=os(o,r))||s.enumerable});return e};var f=(e,o,t)=>(t=e!=null?ss(ns(e)):{},as(o||!e||!e.__esModule?Ie(t,"default",{value:e,enumerable:!0}):t,e));var Yt=require("commander");var Ve=require("commander");var Te=f(require("axios"),1);var K=f(require("keytar"),1),de="smoothcdn",ue="cli_token";async function Oe(e){await K.default.setPassword(de,ue,e)}async function Le(){return process.env.SCDN_TOKEN||K.default.getPassword(de,ue)}async function _e(){await K.default.deletePassword(de,ue)}async function v(){let e=await Le();return Te.default.create({baseURL:"https://smoothcdn.com/api",headers:e?{Authorization:`Bearer ${e}`}:{}})}var We=require("@inquirer/prompts");var Z=f(require("fs"),1),Be=f(require("path"),1);function ge(e=process.cwd()){return Be.default.join(e,".scdn.json")}function Q(){return Z.default.existsSync(ge())}function w(){return Q()?JSON.parse(Z.default.readFileSync(ge(),"utf8")):{}}function P(e){Z.default.writeFileSync(ge(),JSON.stringify(e,null,2))}var Y=f(require("ora"),1),ke=require("date-fns"),Me=require("date-fns/locale"),De=(e,o)=>{let t,s;return o&&(t=o?.status||o?.code,s=o?.response?.data?.error||o?.data?.error||o?.message),`${e}${t?` [${t}]`:""}${s?` [${s}]`:""}`},d=e=>{console.log(e)},O=e=>{(0,Y.default)(e).succeed()},u=(e,o)=>{(0,Y.default)(De(e,o)).fail()},y=e=>(0,Y.default)(e).start(),h=(e,o)=>{o.succeed(e)},g=(e,o,t)=>{o.fail(De(e,t))};function he(e){return typeof e=="string"&&(e=new Date(e)),(0,ke.formatDate)(e,"dd MMMM yyyy HH:mm:ss",{locale:Me.enUS})}function xe(e,o=2){if(!e||e===0)return"0 B";let t=1024,s=o<0?0:o,r=["B","KB","MB","GB","TB"],n=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,n)).toFixed(s))+" "+r[n]}function H(e){if(e==null)return"0";let o=Math.abs(e);return o<1e3?e.toString():o<1e6?(e/1e3).toFixed(e%1e3===0?0:1)+"k":o<1e9?(e/1e6).toFixed(e%1e6===0?0:1)+"M":(e/1e9).toFixed(e%1e9===0?0:1)+"B"}function ze(e){return e.toLowerCase().normalize("NFKD").trim().replace(/[\u0300-\u036f]/g,"").replace(/\s+/g,"-").replace(/[^a-z0-9\-]/g,"").replace(/\-+/g,"-")}var Re=new Ve.Command("create-version").description("Create version for next deployments").argument("[version]","Version number, e.g. 1.0.0").action(async(e="")=>{let o=await v(),t=w();if(!t){u("No .scdn.json found.");return}let s=e||t.version,r=await(0,We.confirm)({message:"Create version as blank (no assets will be copied from previous version automatically) ?",default:!1});if(s){let n=y(`Creating version "${s}"`);try{let a=await o.post(`/projects/${t.projectId}/versions`,{version:s,blank:r,failIfExist:!1});a.status===201?h(`Created new version "${s}"`,n):a.status===200&&h(`Version exist "${s}"`,n),e&&(t.version=e,P(t),d(".scdn.json config file updated"),O(`Using version ${e}`))}catch(a){g(`Cannot create version ${e}`,n,a)}}else u('Missing version. Please run "scdn create-version <version>" first.')});var He=require("commander"),ee=f(require("os"),1),Xe=f(require("open"),1);var Ue=new He.Command("login").description("Authenticate via browser").action(async()=>{let e=await v(),o=y("Starting login..."),t=[];try{let s=ee.default.userInfo();s.username&&t.push(s.username)}catch{}try{let s=ee.default.platform();s&&t.push(s)}catch{}try{let s=ee.default.machine();s&&t.push(s)}catch{}try{let{data:s}=await e.post("/auth/cli",{label:t.join("-")}),{key_id:r,verification_url:n}=s;await(0,Xe.default)(n),o.text="Waiting for authentication...";let a=null;for(;!a;){await new Promise(j=>setTimeout(j,1500));let p=await e.post("/auth/cli/poll",{keyId:r}).catch(()=>null);if(!p?.data)continue;let{status:x}=p.data;if(x!=="pending"){if(x==="expired"){g("Login session expired. Try again.",o);return}if(x==="active"){a=p.data.api_key;break}if(x==="already_active"){g("This login session is already used.",o);return}}}await Oe(a);let i=w(),c=await(await v()).get("/status");c.data&&(i.userSlug=c.data?.slug||"",c.data?.plan>=0&&i?.plan!==c.data?.plan&&(i.plan=c.data.plan),P(i)),h("Login successful!",o)}catch{g("There was an error when authorizing",o)}});var Je=require("commander");var qe=new Je.Command("logout").description("Remove credential data").action(async()=>{await _e(),O("Successfully logged out")});var rt=require("commander"),S=require("@inquirer/prompts"),nt=f(require("clipboardy"),1);var we=require("globby");async function D(e=[],o=[]){let t=await(0,we.globby)(e,{dot:!0});if(o.length===0)return t;let s=await(0,we.globby)(o,{dot:!0});return t.filter(r=>!s.includes(r))}var Ge=["js","mjs","css","json","svg","txt","csv","xml","md"],k=["woff2","woff","ttf","otf"],M=["png","jpg","jpeg","webp","avif"],L=["wav","aiff","aif","flac","mp3","ogg","oga","m4a","aac"],te=["pdf","doc","docx","xls","xlsx","ppt","pptx","odt","ods","odp"],Ke=["json","txt","csv","xml","md","doc","docx","xls","xlsx","ppt","pptx","odt","ods","odp"],ye={0:{projects:1,assetsPerProject:50,bandwidth:1073741824,maxRequests:2e4,maxTextAssetSize:204800,maxImageAssetSize:2097152,maxAudioAssetSize:2097152,usageEventsMaxDays:3,usageEventsMaxAmount:100},1:{projects:10,assetsPerProject:1e4,bandwidth:107374182400,maxRequests:5e6,maxTextAssetSize:512e3,maxImageAssetSize:20971520,maxAudioAssetSize:52428800,usageEventsMaxDays:7,usageEventsMaxAmount:500},2:{projects:50,assetsPerProject:1e5,bandwidth:1099511627776,maxRequests:5e7,maxTextAssetSize:1048576,maxImageAssetSize:52428800,maxAudioAssetSize:104857600,usageEventsMaxDays:14,usageEventsMaxAmount:1e3}};var cs=({url:e,alt:o="",critical:t=!1,width:s,height:r})=>`<img
3
3
  src="${e}"
4
4
  alt="${o}"${t?`
5
5
  fetchpriority="high"
@@ -8,7 +8,7 @@ var ts=Object.create;var Ie=Object.defineProperty;var ss=Object.getOwnPropertyDe
8
8
  decoding="async"`}${s?`
9
9
  width="${s}"`:""}${r?`
10
10
  height="${r}"`:""}
11
- />`,cs=({url:e,scriptType:o="standard"})=>{switch(o){case"critical":return`<link
11
+ />`,ls=({url:e,scriptType:o="standard"})=>{switch(o){case"critical":return`<link
12
12
  rel="preload"
13
13
  as="script"
14
14
  href="${e}"
@@ -22,7 +22,7 @@ var ts=Object.create;var Ie=Object.defineProperty;var ss=Object.getOwnPropertyDe
22
22
  ></script>`;default:return`<script
23
23
  src="${e}"
24
24
  defer
25
- ></script>`}},ls=({url:e,preload:o=!1})=>o?`<link
25
+ ></script>`}},fs=({url:e,preload:o=!1})=>o?`<link
26
26
  rel="preload"
27
27
  as="style"
28
28
  href="${e}"
@@ -33,30 +33,30 @@ var ts=Object.create;var Ie=Object.defineProperty;var ss=Object.getOwnPropertyDe
33
33
  />`:`<link
34
34
  rel="stylesheet"
35
35
  href="${e}"
36
- />`,fs=({url:e,controls:o=!1,loop:t=!1,preload:s="none"})=>`<audio
36
+ />`,ps=({url:e,controls:o=!1,loop:t=!1,preload:s="none"})=>`<audio
37
37
  src="${e}"${s?`
38
38
  preload="${s}"`:""}${o?`
39
39
  controls`:""}${t?`
40
40
  loop`:""}
41
- ></audio>`,ps=({url:e,extension:o,fontFamily:t="",fontDisplay:s="swap"})=>`<style>
41
+ ></audio>`,ms=({url:e,extension:o,fontFamily:t="",fontDisplay:s="swap"})=>`<style>
42
42
  @font-face {
43
43
  font-family: "${t}";
44
44
  src: url("${e}") format("${o}");
45
45
  font-display: ${s};
46
46
  }
47
- </style>`,ms=({url:e,lazy:o=!1,title:t="",width:s="",height:r=""})=>`<iframe
47
+ </style>`,ds=({url:e,lazy:o=!1,title:t="",width:s="",height:r=""})=>`<iframe
48
48
  src="${e}"${o?`
49
49
  loading="lazy"`:""}${t?`
50
50
  title="${t}`:""}${s?`
51
51
  width="${s}"`:""}${r?`
52
52
  height="${r}"`:""}
53
- ></iframe>`,ds=({url:e,assetName:o,newTab:t=!0,download:s=!0,noreferrer:r=!1})=>{let n=[];t&&n.push("noopener"),r&&n.push("noreferrer");let a=n.length?n.join(" "):"";return`<a
53
+ ></iframe>`,us=({url:e,assetName:o,newTab:t=!0,download:s=!0,noreferrer:r=!1})=>{let n=[];t&&n.push("noopener"),r&&n.push("noreferrer");let a=n.length?n.join(" "):"";return`<a
54
54
  href="${e}"${t?`
55
55
  target="_blank"`:""}${a?`
56
56
  rel="${a}"`:""}${s?`
57
57
  download`:""}
58
- >Download ${o}</a>`};function Ke(e={}){let{extension:o}=e;return o==="js"||o==="mjs"?cs(e):o==="css"?ls(e):o==="pdf"?ms(e):o==="svg"||M.includes(o)?as(e):L.includes(o)?fs(e):k.includes(o)?ps(e):ds(e)}var se=f(require("fs"),1),Qe=f(require("crypto"),1),U=f(require("path"),1),Ye=require("image-size"),et=require("fast-xml-parser");var z=f(require("fs"),1),V=f(require("path"),1),Se=V.default.resolve(".scdn");function us(){z.default.existsSync(Se)||z.default.mkdirSync(Se,{recursive:!0})}function ve(e){return us(),V.default.join(Se,e)}function F(e){let o=ve(e);return z.default.existsSync(o)||z.default.mkdirSync(o,{recursive:!0}),o}function b(e,o,t,s){let r=F(e),n=V.default.join(r,`${o}.${t}`);return z.default.writeFileSync(n,s),n}function C(e,o,t){let s=V.default.join(ve(e),`${o}.${t}`);return z.default.existsSync(s)}function E(e,o,t){return V.default.join(ve(e),`${o}.${t}`)}var X=f(require("sharp"),1);async function gs(e){return(0,X.default)(e).png({compressionLevel:9,quality:70,adaptiveFiltering:!0,palette:!0,dither:.5,effort:8}).toBuffer()}async function hs(e){return(0,X.default)(e).jpeg({quality:70,chromaSubsampling:"4:2:0",mozjpeg:!0}).toBuffer()}async function Ee(e,o={}){let t=o.quality??80;return(0,X.default)(e).webp({quality:t,effort:6}).toBuffer()}async function Ce(e,o={}){let t=o.quality??50;return(0,X.default)(e).avif({quality:t,speed:4}).toBuffer()}async function Ze(e,o){let t=o.toLowerCase();return t==="png"?gs(e):t==="jpg"||t==="jpeg"?hs(e):t==="webp"?Ee(e):t==="avif"?Ce(e):e}function xs(e){return Qe.default.createHash("sha256").update(e).digest("hex")}async function tt(e){let o=se.default.readFileSync(e),t=U.default.extname(e).replace(".","").toLowerCase(),s=U.default.basename(e,U.default.extname(e)),r=xs(o);F(r);let n=C(r,s,t),a=C(r,s,"webp"),i=C(r,s,"avif"),l=t==="webp",c=t==="avif";if(n&&(l||a)&&(c||i))return{hash:r,originalExt:t,originalPath:E(r,s,t),processedPaths:[!l&&a?E(r,s,"webp"):null,!c&&i?E(r,s,"avif"):null].filter(Boolean)};let p=await Ze(o,t),x=l?null:await Ee(o),I=c?null:await Ce(o),m=b(r,s,t,p),$=!l&&x?b(r,s,"webp",x):null,B=!c&&I?b(r,s,"avif",I):null;return{hash:r,originalExt:t,originalPath:m,processedPaths:[$,B].filter(me=>!me?.endsWith(".scdn"))}}function st(e){if(U.default.extname(e).toLowerCase().replace(".","")==="svg"){let r=se.default.readFileSync(e,"utf-8"),i=new et.XMLParser({ignoreAttributes:!1}).parse(r)?.svg;if(!i)return null;if(i["@_width"]&&i["@_height"])return{width:parseFloat(i["@_width"]),height:parseFloat(i["@_height"])};if(i["@_viewBox"]){let[,,l,c]=i["@_viewBox"].split(/\s+/).map(Number);if(l&&c)return{width:l,height:c}}return null}let t=se.default.readFileSync(e),s=(0,Ye.imageSize)(t);return!s.width||!s.height?null:{width:s.width,height:s.height}}function ws(e,o,t,s,r=""){return t?`https://${t}.smoothcdn.com${r?`/${r}`:""}${s}`:`https://cdn.smoothcdn.com/${e}/${o}${r?`/${r}`:""}${s}`}var nt=new ot.Command("get-snippet").description("Output snippet for asset").action(async()=>{let e=w();if(!e){u("No .scdn.json found.");return}let o=await D(e.sources,e.excludes);if(o.length<=0){u("No assets found");return}d(`Found assets ${o.length}`);let t=await(0,S.select)({message:"What asset to get snippet for:",choices:o.map(c=>({name:c,value:c}))}),[,...s]=t.split("/"),r=`/${s.join("/")}`,n=t.split(".").pop()?.toLowerCase()??"",a=ws(e.userSlug,e.projectSlug,e.customSubdomain||"",r,e.version||""),i={extension:n,url:a,assetName:t};if(n==="svg"||M.includes(n)){let c=await st(t);i.alt=await(0,S.input)({message:"Alt attribute",validate:p=>p?!0:"Alt attribute is required",default:t}),i.critical=await(0,S.confirm)({message:"Is critical asset (must be loaded above the fold e.g. in hero section)"}),i.width=await(0,S.input)({message:"Width",default:c?.width?.toString()||""}),i.height=await(0,S.input)({message:"Height",default:c?.height?.toString()||""})}(n==="js"||n==="mjs")&&(i.type=await(0,S.select)({message:"Script type",choices:[{name:"Standard",value:"standard"},{name:"Critical",value:"critical"},{name:"Asynchronous",value:"async"}]})),n==="css"&&(i.preload=await(0,S.confirm)({message:"Preload"})),L.includes(n)&&(i.controls=await(0,S.confirm)({message:"Controls attribute (shows audio control buttons)"}),i.loop=await(0,S.confirm)({message:"Loop attribute (plays audio in loop)"})),k.includes(n)&&(i.fontFamily=await(0,S.input)({message:"Font family",default:t})),n==="pdf"&&(i.lazy=await(0,S.confirm)({message:"Lazy load"}),i.title=await(0,S.input)({message:"Title",default:t}),i.width=await(0,S.input)({message:"Width",default:"100%"}),i.height=await(0,S.input)({message:"Height",default:"600"})),Ge.includes(n)&&(i.newTab=await(0,S.confirm)({message:"Open in new tab"}),i.noreferrer=await(0,S.confirm)({message:'Hide referrer (adds "noreferrer" to rel attribute)'}),i.download=await(0,S.confirm)({message:"Download attribute"}));let l=Ke(i);await rt.default.write(l),d(""),d(l),d(""),O("Snippet was copied to clipboard")});var ct=require("commander"),J=require("@inquirer/prompts");var it=f(require("micromatch"),1);function oe(e){if(!e)return!1;let o=e.trim();return o.length<6||o.length>254||o.includes("..")?!1:/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(o)}function re(e=0,o,t){let{maxTextAssetSize:s,maxImageAssetSize:r}=ye[e],n=o.split(".").pop()?.toLowerCase()??"",a=qe.includes(n),i=k.includes(n),l=M.includes(n),c=L.includes(n),p=te.includes(n);return!a&&!i&&!l&&!c&&!p?`Unsupported file type: ${n}`:(a||i)&&t>s?`Asset too large. Max allowed ${Math.round(s/1024)} KB, trying to send ${Math.round(t/1024)} KB`:(l||p)&&t>r?`Asset too large. Max allowed ${Math.round(r/(1024*1024))} MB, trying to send ${(t/1024/1024).toFixed(2)} MB`:!0}function at(e=0,o,t){let{maxAudioAssetSize:s}=ye[e],r=o.split(".").pop()?.toLowerCase()??"";return L.includes(r)&&t>s?`Asset too large. Max allowed ${Math.round(s/(1024*1024))} MB, received ${(t/1024/1024).toFixed(2)} MB`:!0}function $e(e){try{it.default.matcher(e)}catch{return"Invalid pattern"}return e.includes("\0")||e.includes("..")||e.includes("~")||e.startsWith("/")||/^[A-Za-z]:\\/.test(e)?"Contains invalid segments":!0}var lt=new ct.Command("grant-access").description("Grant access for smooth resources").option("--force","Override expiration date if access already exists").action(async({force:e=!1})=>{let o=await v(),t=w();if(!t){u("No .scdn.json found.");return}let r=((await o.get(`/projects/${t.projectId}/assets`)).data??[]).filter(n=>n.protected).map(n=>`${n.path}${n.fileName}`);if(r.length===0)u("No protected assets found");else{let n=await(0,J.checkbox)({message:"Select protected assets to grant access to:",choices:r.map(c=>({name:c,value:c})),validate:c=>c.length>0?!0:"Select at least one asset."}),a=await(0,J.input)({message:"Enter user email to grant access (mail@example.com):",validate:c=>oe(c)?!0:"Invalid mail format"}),i=await(0,J.input)({message:"Enter expiration date (leave empty if no expiration should be set):"}),l=y("Granting access...");try{let c={force:e,assets:n,email:a,expiresAt:i},p=await o.post(`/projects/${t.projectId}/accesses/grant`,c);p.status===201?h(`Access granted for "${a}"`,l):p.status===200?h(`Access already exists for "${a}"`,l):g("Unexpected response from server",l,p)}catch(c){g("Failed to grant access",l,c)}}});var kt=require("commander"),N=require("@inquirer/prompts");var _t=require("commander"),Tt=f(require("form-data"),1),q=f(require("fs"),1),Pe=f(require("path"),1);var ft=f(require("fs"),1),pt=f(require("crypto"),1),ne=f(require("path"),1),be=require("child_process");function ys(e){return pt.default.createHash("sha256").update(e).digest("hex")}function Ss(){try{return(0,be.execFileSync)("ffmpeg",["-version"],{stdio:"ignore"}),!0}catch{return!1}}function vs(e,o){(0,be.execFileSync)("ffmpeg",["-y","-i",e,"-map_metadata","-1","-vn","-c:a","aac","-q:a","2","-movflags","+faststart",o],{stdio:"ignore"})}async function mt(e){if(!Ss())return!1;let o=ft.default.readFileSync(e),t=ne.default.extname(e).replace(".","").toLowerCase(),s=ne.default.basename(e,ne.default.extname(e));if(!L.includes(t))throw new Error(`Unsupported audio extension: .${t}`);let r=ys(o);F(r);let n=C(r,s,t),a=C(r,s,"m4a"),i=n?E(r,s,t):b(r,s,t,o);if(a)return{hash:r,originalExt:t,originalPath:i,processedPaths:[E(r,s,"m4a")]};let l=E(r,s,"m4a");return vs(i,l),{hash:r,originalExt:t,originalPath:i,processedPaths:[l]}}var dt=f(require("fs"),1),ut=f(require("crypto"),1),ie=f(require("path"),1),gt=f(require("postcss"),1),ht=f(require("cssnano"),1);function Es(e){return ut.default.createHash("sha256").update(e).digest("hex")}function Cs(e){let o=e.split(`
59
- `),t=o.reduce((n,a)=>n+a.length,0)/o.length,s=(e.match(/\s/g)?.length??0)/e.length,r=/\/\*/.test(e);return t>200&&s<.12&&!r}async function $s(e){return(await(0,gt.default)([(0,ht.default)({preset:["default",{discardComments:!0,normalizeWhitespace:!0,mergeRules:!1,mergeLonghand:!1,reduceIdents:!1,zindex:!1,calc:!1,colormin:!1,normalizeUrls:!1,normalizeTimingFunctions:!1,normalizeUnicode:!1,minifyFontValues:!1,minifySelectors:!1}]})]).process(e,{from:void 0})).css}async function xt(e){let o=dt.default.readFileSync(e),t=ie.default.extname(e).replace(".","").toLowerCase(),s=ie.default.basename(e,ie.default.extname(e)),r=Es(o);if(F(r),C(r,s,t))return{hash:r,originalExt:t,originalPath:E(r,s,t)};let a=o.toString("utf8"),i=o;if(!Cs(a)){let p=await $s(a);i=Buffer.from(p)}let c=b(r,s,t,i);return{hash:r,originalExt:t,originalPath:c}}var vt=f(require("fs"),1),Et=f(require("crypto"),1),ae=f(require("path"),1);var wt=f(require("ttf2woff2"),1);async function yt(e,o){return e}async function St(e){return Buffer.from((0,wt.default)(e))}function bs(e){return Et.default.createHash("sha256").update(e).digest("hex")}async function Ct(e){let o=vt.default.readFileSync(e),t=ae.default.extname(e).replace(".","").toLowerCase(),s=ae.default.basename(e,ae.default.extname(e)),r=bs(o);F(r);let n=C(r,s,t),a=C(r,s,"woff2"),i=t==="woff2";if(n&&(i||a))return{hash:r,originalExt:t,originalPath:E(r,s,t),processedPaths:[!i&&a?E(r,s,"woff2"):null].filter(Boolean)};let l=await yt(o,t),c=i?null:await St(o),p=b(r,s,t,l),x=!i&&c?b(r,s,"woff2",c):null;return{hash:r,originalExt:t,originalPath:p,processedPaths:[x].filter(I=>I&&!I.endsWith(".scdn"))}}var Ae=f(require("fs"),1),$t=f(require("crypto"),1),ce=f(require("path"),1),bt=require("terser");function As(e){return $t.default.createHash("sha256").update(e).digest("hex")}async function Ps(e){return(await(0,bt.minify)(e,{compress:!1,mangle:{toplevel:!1},format:{comments:!1,semicolons:!0}})).code}function Fs(e){let o=e.split(`
60
- `),t=o.reduce((r,n)=>r+n.length,0)/o.length,s=(e.match(/\s/g)?.length??0)/e.length;return t>200&&s<.15&&!/\/\*|\n\s*\/\//.test(e)}async function At(e){let o=Ae.default.readFileSync(e),t=ce.default.extname(e).replace(".","").toLowerCase(),s=ce.default.basename(e,ce.default.extname(e)),r=As(o);if(F(r),C(r,s,t))return{hash:r,originalExt:t,originalPath:E(r,s,t)};let a=Ae.default.readFileSync(e),i=a.toString("utf8"),l=a;if(!Fs(i)){let x=await Ps(i);l=Buffer.from(x)}let p=b(r,s,t,l);return{hash:r,originalExt:t,originalPath:p}}var Pt=f(require("fs"),1),Ft=f(require("crypto"),1),le=f(require("path"),1);function Ns(e){return Ft.default.createHash("sha256").update(e).digest("hex")}function js(e){let o=(e.match(/\s/g)?.length??0)/e.length,t=e.split(`
61
- `).length;return o<.08&&t<=2}function Is(e){let o=JSON.parse(e);return JSON.stringify(o)}async function Nt(e){let o=Pt.default.readFileSync(e),t=le.default.extname(e).replace(".","").toLowerCase(),s=le.default.basename(e,le.default.extname(e)),r=Ns(o);if(F(r),C(r,s,t))return{hash:r,originalExt:t,originalPath:E(r,s,t)};let a=o.toString("utf8"),i=o;if(!js(a)){let p=Is(a);i=Buffer.from(p)}if(!i||i.length===0)throw new Error("JSON minification produced empty output");let c=b(r,s,t,i);return{hash:r,originalExt:t,originalPath:c}}var jt=f(require("fs"),1),It=f(require("crypto"),1),fe=f(require("path"),1),Ot=require("svgo");function Os(e){return It.default.createHash("sha256").update(e).digest("hex")}function Ls(e){let o=(e.match(/\s/g)?.length??0)/e.length,t=/<!--/.test(e),s=e.split(`
62
- `).length;return o<.1&&s<=2&&!t}function _s(e){let o=console.warn,t=console.info;console.warn=()=>{},console.info=()=>{};let s;try{s=(0,Ot.optimize)(e,{multipass:!0,plugins:[{name:"preset-default",params:{overrides:{convertPathData:!1,convertStyleToAttrs:!1,cleanupIds:!1,removeViewBox:!1,inlineStyles:!1}}},"removeUselessStrokeAndFill"]})}finally{console.warn=o,console.info=t}if(!("data"in s)||!s.data)throw new Error("SVG optimization failed");return s.data}async function Lt(e){let o=jt.default.readFileSync(e),s=fe.default.parse(e).ext.replace(".","").toLowerCase(),r=fe.default.basename(e,fe.default.extname(e)),n=Os(o);if(F(n),C(n,r,s))return{hash:n,originalExt:s,originalPath:E(n,r,s)};let i=o.toString("utf8"),l=o;if(!Ls(i)){let x=_s(i);l=Buffer.from(x)}let p=b(n,r,s,l);return{hash:n,originalExt:s,originalPath:p}}var Fe=async({force:e=!1,sync:o=!1})=>{let t=await v(),s=w();if(!s){u("No .scdn.json found.");return}let r=!1;if(!s.projectId)u('Missing projectId in config file. Please run "scdn init" or "scdn load" command first.');else try{let n=await t.get("/status"),{plan:a,slug:i}=n.data;s.plan!==a&&(s.plan=a,P(s)),s.userSlug!==i&&(s.userSlug=i,P(s)),d(`Deploying assets${s.version?` for version ${s.version}`:""}...`);let l=await D(s.sources,s.excludes),c=await D(s.protected),p=[];if(l.length>0){let x=y("Deploying asset"),I=0;for(let m of l)if(++I,r&&!e)g(`Selected version was already published "${m}"`,x);else try{let $=Pe.default.basename(m),me=m.replace($,"").replace(/^\/+|\/+$/g,""),[,...es]=me.split("/"),Ne=es.join("/"),G=0;try{G=q.default.statSync(m).size}catch{throw new Error(`Cannot read file: ${m}`)}let je=re(s.plan||0,$,G);if(je!==!0)throw new Error(je);let _=$.split(".").pop()?.toLowerCase()??"",A;if(M.includes(_)&&_!=="avif")A=await tt(m);else if(_==="js"||_==="mjs")A=await At(m);else if(_==="css")A=await xt(m);else if(_==="json")A=await Nt(m);else if(_==="svg")A=await Lt(m);else if(k.includes(_))A=await Ct(m);else if(L.includes(_)){if(A=await mt(m),A===!1)throw new Error("To optimize audio - ffmpeg is required. Install it from https://ffmpeg.org/");if(A?.originalPath){try{G=q.default.statSync(A.originalPath).size}catch{throw new Error(`Cannot read file: ${A.originalPath}`)}let R=at(s.plan||0,Pe.default.basename(A.originalPath),G);if(R!==!0)throw new Error(R)}else throw new Error("Audio was not optimized")}else te.includes(_)&&(A={originalPath:m,processedPaths:[]});let T=new Tt.default;T.append("asset",q.default.createReadStream(A?.originalPath?A.originalPath:m)),A?.processedPaths?.forEach(R=>{T.append("sub_assets[]",q.default.createReadStream(R))}),T.append("path",Ne),T.append("version",s.version||""),T.append("optimize",0),T.append("failIfExist",0),T.append("protected",c.includes(m)?1:0),e&&T.append("force",1),p.push({fileName:$,path:Ne});let W=await t.post(`/projects/${s.projectId}/assets`,T,{headers:T.getHeaders()});W.status===201?h(`Deployed "${m}"`,x):W.status===200&&(W.data?.error==="Cannot deploy/override assets on published version"?(r=!0,g(`Failed to deploy ${m}`,x,W)):W.data?.dedupe&&h(`Asset already exists "${m}"`,x))}catch($){g(`Failed to deploy ${m}`,x,$)}if(o){let m=y("Sync...");try{let $=await t.post(`/projects/${s.projectId}/assets/sync`,{force:e,version:s.version,assetsToSync:p});h(`Sync: ${$?.data?.removed??0} files removed`,m)}catch($){g($,m)}}}else u("No assets to deploy")}catch(n){u("Cannot proceed with pushing assets",n)}d("")},Bt=new _t.Command("push").option("--force","Override assets on published versions too").option("--sync","Additionally removes files that do not exists in project anymore").description("Push assets to CDN").action(Fe);var Mt=new kt.Command("init").description("Initialize new project").action(async()=>{let e=await v(),o=!1;if(Q())d("Detected .scdn.json config file");else{let t=await(0,N.input)({message:"Project name:"});o=await(0,N.confirm)({message:"Enable versioning:",default:!1});let s=o?await(0,N.input)({message:"Initial version:",default:"1.0.0"}):"",r=await(0,N.confirm)({message:"Block bots for this variant?",default:!1}),n=await(0,N.confirm)({message:"Block headless browsers?",default:!1}),a=[],i=!0;for(;i;){let m=await(0,N.input)({message:"Add source path/pattern (glob allowed):",validate:B=>B.trim().length>0||"Source required"});a.push(m.trim()),i=await(0,N.confirm)({message:"Add another source?",default:!1})}let l=[];if(await(0,N.confirm)({message:"Add exclude patterns?",default:!1})){let m=!0;for(;m;){let $=await(0,N.input)({message:"Exclude path/pattern:",validate:B=>B.trim().length>0||"Exclude required"});l.push($.trim()),m=await(0,N.confirm)({message:"Add another exclude?",default:!1})}}let p=[];if(await(0,N.confirm)({message:"Add protected patterns?",default:!1})){let m=!0;for(;m;){let $=await(0,N.input)({message:"Protected path/pattern:",validate:B=>B.trim().length>0||"Protected required"});p.push($.trim()),m=await(0,N.confirm)({message:"Add another protected?",default:!1})}}P({project:t,version:s,blockBots:r,blockHeadless:n,sources:a,excludes:l,protected:p}),d("Created .scdn.json config file")}if(Q()){d("Sending to Smooth CDN...");let t=w(),s,r=y(`Creating project "${t.project}"`);try{s=await e.post("/projects",{name:t.project,slug:t.projectSlug||"",withVersioning:o||!!t?.version,version:o||t?.version?t.version:"",block_bots:t.blockBots,block_headless:t.blockHeadless,sources:t?.sources||[],excludes:t?.excludes||[],protected:t?.protected||[],failIfExist:!1}),s.status===201?h(`Created new project "${t.project} ${t.version}"`,r):s.status===200&&h(`Project exist "${t.project} ${t.version}"`,r),s.data.id&&s.data.id!==t.projectId&&(t.projectId=s.data.id,P(t)),await Fe({force:!1}),d("Sent to Smooth CDN")}catch(n){g("Cannot create project",r,n)}}});var Dt=require("commander"),zt=f(require("fs"),1),Vt=f(require("path"),1);var Wt=new Dt.Command("inspect-assets").description("Validates assets paths and lists assets for deployments").action(async()=>{let e=w();if(!e){u("No .scdn.json found.");return}d("Checking paths"),e?.sources?.forEach(t=>{let s=$e(t);s?O(t):u(`${t} [${s}]`)}),e?.excludes?.forEach(t=>{let s=$e(t);s?O(t):u(`${t} [${s}]`)}),d("Checking assets:");let o=await D(e.sources,e.excludes);o.length===0?u("No assets found"):o.forEach(t=>{let s=Vt.default.basename(t),r=0;try{r=zt.default.statSync(t).size}catch{throw new Error(`Cannot read file: ${t}`)}let n=re(e.plan||0,s,r);n===!0?O(s):u(`${s} [${n}]`)}),d("")});var Rt=require("commander"),Ht=require("@inquirer/prompts");var Xt=new Rt.Command("load").description("Initialize project that already exists").action(async()=>{let e=w();if(e?.project&&e?.projectSlug)O("Project already initiated in .scdn config file.");else{let o=y("Fetching available projects...");try{let s=await(await v()).get("/projects?full=1");if(s.data.length>0){h(`${s.data.length} projects available`,o);let r=await(0,Ht.select)({message:"Which project to load:",choices:s.data.map(a=>({name:a.name,value:a.id}))}),n=s.data.find(a=>a.id===r);P({...e,project:n.name,projectId:n.id,projectSlug:n.slug,customSubdomain:n?.customSubdomain||"",version:n.withVersioning?n.latestVersion||n?.versions[0]?.version||"1.0.0":"",blockBots:!!n.blockBots,blockHeadless:!!n.blockHeadless,sources:n?.sources?JSON.parse(n.sources):[],excludes:n?.excludes?JSON.parse(n.excludes):[],protected:n?.protected?JSON.parse(n.protected):[]}),O("Config file saved")}else g("No projects available to be loaded from Smooth CDN",o)}catch(t){g("Failed to fetch projects",o,t)}}});var Ut=require("commander");var Jt=new Ut.Command("publish-version").description("Publish selected version").argument("[version]","Version number, e.g. 1.0.0").action(async(e="")=>{let o=await v(),t=w();if(!t){u("No .scdn.json found.");return}let s=e||t.version;if(s){let r=y(`Publishing version "${s}"`);try{let n=await o.post(`/projects/${t.projectId}/versions/publish`,{version:s});n.status===201?h(`Published new version "${s}"`,r):n.status===200&&h(`Version already published "${s}"`,r)}catch(n){g(`Cannot publish version ${s}`,r,n)}}else u('Missing version. Please run "scdn create-version <version>" first.')});var qt=require("commander"),pe=require("@inquirer/prompts");var Gt=new qt.Command("revoke-access").description("Revoke access for smooth resources").action(async()=>{let e=await v(),o=w();if(!o){u("No .scdn.json found.");return}let t=await(0,pe.input)({message:"Enter user email to revoke access (mail@example.com):",validate:s=>oe(s)?!0:"Invalid mail format"});try{let s=y("Revoking access..."),r=await e.post("/customer/accesses",{email:t});r.data?.length<=0&&g(`No accesses found for "${t}"`,s),h(`Fetched ${r.data.length} accesses`,s);let n=await(0,pe.select)({message:"What access to revoke:",choices:r.data.map(l=>({name:`${l.project} (${l.assets.join(",")})`,value:l.id}))}),a=y("Revoking access..."),i=await e.post(`/projects/${o.projectId}/accesses/${n}/revoke`);i.status===201?h("Selected access revoked",a):i.status===200?h("Selected access already revoked",a):g("Failed to revoke access",a)}catch(s){u("Failed to revoke access",s)}});var Kt=require("commander");var Ts=["FREE","PRO","PREMIUM"],Zt=new Kt.Command("status").description("Get a status summary").action(async()=>{let e=await v(),o=await w();if(!o){u("No .scdn.json found.");return}let t,s=y("Fetching status...");try{t=await e.get("/status"),h("Fetched",s);try{let{name:r,email:n,plan:a,slug:i,planExpiration:l,limits:c,usage:p,projects:x=[]}=t.data;o.plan!==a&&(o.plan=a,P(o)),o.userSlug!==i&&(o.userSlug=i,P(o)),d(`Logged in as ${r} (${i} - ${n})`),d(`Plan: ${Ts[a]} ${l?`(Expires at ${he(l)})`:""}`),p&&(d("Usage limits:"),d(` Requests: ${H(p.requests)}/${H(p.maxRequests)}`),d(` Bandwidth: ${xe(p.bandwidth)}/${xe(p.maxBandwidth)}`),p.periodEnd&&d(` Resets at: ${he(p.periodEnd)}`)),d(""),d(`Projects (used projects: ${x.length}/${c.projects}):`),x.map((I,m)=>{d(` ${m+1}. ${I.name} (used assets: ${H(I.assetsCount)}/${H(c.assetsPerProject)})`)})}catch(r){g("Failed to parse status",s,r)}}catch(r){g("Failed to parse status",s,r)}});var Yt=require("module"),Ms={},Bs=(0,Yt.createRequire)(Ms.url),ks=Bs("../package.json"),j=new Qt.Command;j.name("scdn").description("Smooth CDN CLI").version(ks.version);j.addCommand(We);j.addCommand(nt);j.addCommand(lt);j.addCommand(Mt);j.addCommand(Wt);j.addCommand(Xt);j.addCommand(Xe);j.addCommand(Je);j.addCommand(Jt);j.addCommand(Bt);j.addCommand(Gt);j.addCommand(Zt);j.parse();
58
+ >Download ${o}</a>`};function Ze(e={}){let{extension:o}=e;return o==="js"||o==="mjs"?ls(e):o==="css"?fs(e):o==="pdf"?ds(e):o==="svg"||M.includes(o)?cs(e):L.includes(o)?ps(e):k.includes(o)?ms(e):us(e)}var se=f(require("fs"),1),Ye=f(require("crypto"),1),U=f(require("path"),1),et=require("image-size"),tt=require("fast-xml-parser");var z=f(require("fs"),1),V=f(require("path"),1),Se=V.default.resolve(".scdn");function gs(){z.default.existsSync(Se)||z.default.mkdirSync(Se,{recursive:!0})}function ve(e){return gs(),V.default.join(Se,e)}function F(e){let o=ve(e);return z.default.existsSync(o)||z.default.mkdirSync(o,{recursive:!0}),o}function b(e,o,t,s){let r=F(e),n=V.default.join(r,`${o}.${t}`);return z.default.writeFileSync(n,s),n}function C(e,o,t){let s=V.default.join(ve(e),`${o}.${t}`);return z.default.existsSync(s)}function E(e,o,t){return V.default.join(ve(e),`${o}.${t}`)}var X=f(require("sharp"),1);async function hs(e){return(0,X.default)(e).png({compressionLevel:9,quality:70,adaptiveFiltering:!0,palette:!0,dither:.5,effort:8}).toBuffer()}async function xs(e){return(0,X.default)(e).jpeg({quality:70,chromaSubsampling:"4:2:0",mozjpeg:!0}).toBuffer()}async function Ee(e,o={}){let t=o.quality??80;return(0,X.default)(e).webp({quality:t,effort:6}).toBuffer()}async function Ce(e,o={}){let t=o.quality??50;return(0,X.default)(e).avif({quality:t,speed:4}).toBuffer()}async function Qe(e,o){let t=o.toLowerCase();return t==="png"?hs(e):t==="jpg"||t==="jpeg"?xs(e):t==="webp"?Ee(e):t==="avif"?Ce(e):e}function ws(e){return Ye.default.createHash("sha256").update(e).digest("hex")}async function st(e){let o=se.default.readFileSync(e),t=U.default.extname(e).replace(".","").toLowerCase(),s=U.default.basename(e,U.default.extname(e)),r=ws(o);F(r);let n=C(r,s,t),a=C(r,s,"webp"),i=C(r,s,"avif"),l=t==="webp",c=t==="avif";if(n&&(l||a)&&(c||i))return{hash:r,originalExt:t,originalPath:E(r,s,t),processedPaths:[!l&&a?E(r,s,"webp"):null,!c&&i?E(r,s,"avif"):null].filter(Boolean)};let p=await Qe(o,t),x=l?null:await Ee(o),j=c?null:await Ce(o),m=b(r,s,t,p),$=!l&&x?b(r,s,"webp",x):null,B=!c&&j?b(r,s,"avif",j):null;return{hash:r,originalExt:t,originalPath:m,processedPaths:[$,B].filter(me=>!me?.endsWith(".scdn"))}}function ot(e){if(U.default.extname(e).toLowerCase().replace(".","")==="svg"){let r=se.default.readFileSync(e,"utf-8"),i=new tt.XMLParser({ignoreAttributes:!1}).parse(r)?.svg;if(!i)return null;if(i["@_width"]&&i["@_height"])return{width:parseFloat(i["@_width"]),height:parseFloat(i["@_height"])};if(i["@_viewBox"]){let[,,l,c]=i["@_viewBox"].split(/\s+/).map(Number);if(l&&c)return{width:l,height:c}}return null}let t=se.default.readFileSync(e),s=(0,et.imageSize)(t);return!s.width||!s.height?null:{width:s.width,height:s.height}}function ys(e,o,t,s,r=""){return t?`https://${t}.smoothcdn.com${r?`/${r}`:""}${s}`:`https://cdn.smoothcdn.com/${e}/${o}${r?`/${r}`:""}${s}`}var it=new rt.Command("get-snippet").description("Output snippet for asset").action(async()=>{let e=w();if(!e){u("No .scdn.json found.");return}let o=await D(e.sources,e.excludes);if(o.length<=0){u("No assets found");return}d(`Found assets ${o.length}`);let t=await(0,S.select)({message:"What asset to get snippet for:",choices:o.map(c=>({name:c,value:c}))}),[,...s]=t.split("/"),r=`/${s.join("/")}`,n=t.split(".").pop()?.toLowerCase()??"",a=ys(e.userSlug,e.projectSlug,e.customSubdomain||"",r,e.version||""),i={extension:n,url:a,assetName:t};if(n==="svg"||M.includes(n)){let c=await ot(t);i.alt=await(0,S.input)({message:"Alt attribute",validate:p=>p?!0:"Alt attribute is required",default:t}),i.critical=await(0,S.confirm)({message:"Is critical asset (must be loaded above the fold e.g. in hero section)"}),i.width=await(0,S.input)({message:"Width",default:c?.width?.toString()||""}),i.height=await(0,S.input)({message:"Height",default:c?.height?.toString()||""})}(n==="js"||n==="mjs")&&(i.type=await(0,S.select)({message:"Script type",choices:[{name:"Standard",value:"standard"},{name:"Critical",value:"critical"},{name:"Asynchronous",value:"async"}]})),n==="css"&&(i.preload=await(0,S.confirm)({message:"Preload"})),L.includes(n)&&(i.controls=await(0,S.confirm)({message:"Controls attribute (shows audio control buttons)"}),i.loop=await(0,S.confirm)({message:"Loop attribute (plays audio in loop)"})),k.includes(n)&&(i.fontFamily=await(0,S.input)({message:"Font family",default:t})),n==="pdf"&&(i.lazy=await(0,S.confirm)({message:"Lazy load"}),i.title=await(0,S.input)({message:"Title",default:t}),i.width=await(0,S.input)({message:"Width",default:"100%"}),i.height=await(0,S.input)({message:"Height",default:"600"})),Ke.includes(n)&&(i.newTab=await(0,S.confirm)({message:"Open in new tab"}),i.noreferrer=await(0,S.confirm)({message:'Hide referrer (adds "noreferrer" to rel attribute)'}),i.download=await(0,S.confirm)({message:"Download attribute"}));let l=Ze(i);await nt.default.write(l),d(""),d(l),d(""),O("Snippet was copied to clipboard")});var lt=require("commander"),J=require("@inquirer/prompts");var at=f(require("micromatch"),1);function oe(e){if(!e)return!1;let o=e.trim();return o.length<6||o.length>254||o.includes("..")?!1:/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(o)}function re(e=0,o,t){let{maxTextAssetSize:s,maxImageAssetSize:r}=ye[e],n=o.split(".").pop()?.toLowerCase()??"",a=Ge.includes(n),i=k.includes(n),l=M.includes(n),c=L.includes(n),p=te.includes(n);return!a&&!i&&!l&&!c&&!p?`Unsupported file type: ${n}`:(a||i)&&t>s?`Asset too large. Max allowed ${Math.round(s/1024)} KB, trying to send ${Math.round(t/1024)} KB`:(l||p)&&t>r?`Asset too large. Max allowed ${Math.round(r/(1024*1024))} MB, trying to send ${(t/1024/1024).toFixed(2)} MB`:!0}function ct(e=0,o,t){let{maxAudioAssetSize:s}=ye[e],r=o.split(".").pop()?.toLowerCase()??"";return L.includes(r)&&t>s?`Asset too large. Max allowed ${Math.round(s/(1024*1024))} MB, received ${(t/1024/1024).toFixed(2)} MB`:!0}function $e(e){try{at.default.matcher(e)}catch{return"Invalid pattern"}return e.includes("\0")||e.includes("..")||e.includes("~")||e.startsWith("/")||/^[A-Za-z]:\\/.test(e)?"Contains invalid segments":!0}var ft=new lt.Command("grant-access").description("Grant access for smooth resources").option("--force","Override expiration date if access already exists").action(async({force:e=!1})=>{let o=await v(),t=w();if(!t){u("No .scdn.json found.");return}let r=((await o.get(`/projects/${t.projectId}/assets`)).data??[]).filter(n=>n.protected).map(n=>`${n.path}${n.fileName}`);if(r.length===0)u("No protected assets found");else{let n=await(0,J.checkbox)({message:"Select protected assets to grant access to:",choices:r.map(c=>({name:c,value:c})),validate:c=>c.length>0?!0:"Select at least one asset."}),a=await(0,J.input)({message:"Enter user email to grant access (mail@example.com):",validate:c=>oe(c)?!0:"Invalid mail format"}),i=await(0,J.input)({message:"Enter expiration date (leave empty if no expiration should be set):"}),l=y("Granting access...");try{let c={force:e,assets:n,email:a,expiresAt:i},p=await o.post(`/projects/${t.projectId}/accesses/grant`,c);p.status===201?h(`Access granted for "${a}"`,l):p.status===200?h(`Access already exists for "${a}"`,l):g("Unexpected response from server",l,p)}catch(c){g("Failed to grant access",l,c)}}});var Mt=require("commander"),N=require("@inquirer/prompts");var Tt=require("commander"),Bt=f(require("form-data"),1),q=f(require("fs"),1),Pe=f(require("path"),1);var pt=f(require("fs"),1),mt=f(require("crypto"),1),ne=f(require("path"),1),be=require("child_process");function Ss(e){return mt.default.createHash("sha256").update(e).digest("hex")}function vs(){try{return(0,be.execFileSync)("ffmpeg",["-version"],{stdio:"ignore"}),!0}catch{return!1}}function Es(e,o){(0,be.execFileSync)("ffmpeg",["-y","-i",e,"-map_metadata","-1","-vn","-c:a","aac","-q:a","2","-movflags","+faststart",o],{stdio:"ignore"})}async function dt(e){if(!vs())return!1;let o=pt.default.readFileSync(e),t=ne.default.extname(e).replace(".","").toLowerCase(),s=ne.default.basename(e,ne.default.extname(e));if(!L.includes(t))throw new Error(`Unsupported audio extension: .${t}`);let r=Ss(o);F(r);let n=C(r,s,t),a=C(r,s,"m4a"),i=n?E(r,s,t):b(r,s,t,o);if(a)return{hash:r,originalExt:t,originalPath:i,processedPaths:[E(r,s,"m4a")]};let l=E(r,s,"m4a");return Es(i,l),{hash:r,originalExt:t,originalPath:i,processedPaths:[l]}}var ut=f(require("fs"),1),gt=f(require("crypto"),1),ie=f(require("path"),1),ht=f(require("postcss"),1),xt=f(require("cssnano"),1);function Cs(e){return gt.default.createHash("sha256").update(e).digest("hex")}function $s(e){let o=e.split(`
59
+ `),t=o.reduce((n,a)=>n+a.length,0)/o.length,s=(e.match(/\s/g)?.length??0)/e.length,r=/\/\*/.test(e);return t>200&&s<.12&&!r}async function bs(e){return(await(0,ht.default)([(0,xt.default)({preset:["default",{discardComments:!0,normalizeWhitespace:!0,mergeRules:!1,mergeLonghand:!1,reduceIdents:!1,zindex:!1,calc:!1,colormin:!1,normalizeUrls:!1,normalizeTimingFunctions:!1,normalizeUnicode:!1,minifyFontValues:!1,minifySelectors:!1}]})]).process(e,{from:void 0})).css}async function wt(e){let o=ut.default.readFileSync(e),t=ie.default.extname(e).replace(".","").toLowerCase(),s=ie.default.basename(e,ie.default.extname(e)),r=Cs(o);if(F(r),C(r,s,t))return{hash:r,originalExt:t,originalPath:E(r,s,t)};let a=o.toString("utf8"),i=o;if(!$s(a)){let p=await bs(a);i=Buffer.from(p)}let c=b(r,s,t,i);return{hash:r,originalExt:t,originalPath:c}}var Et=f(require("fs"),1),Ct=f(require("crypto"),1),ae=f(require("path"),1);var yt=f(require("ttf2woff2"),1);async function St(e,o){return e}async function vt(e){return Buffer.from((0,yt.default)(e))}function As(e){return Ct.default.createHash("sha256").update(e).digest("hex")}async function $t(e){let o=Et.default.readFileSync(e),t=ae.default.extname(e).replace(".","").toLowerCase(),s=ae.default.basename(e,ae.default.extname(e)),r=As(o);F(r);let n=C(r,s,t),a=C(r,s,"woff2"),i=t==="woff2";if(n&&(i||a))return{hash:r,originalExt:t,originalPath:E(r,s,t),processedPaths:[!i&&a?E(r,s,"woff2"):null].filter(Boolean)};let l=await St(o,t),c=i?null:await vt(o),p=b(r,s,t,l),x=!i&&c?b(r,s,"woff2",c):null;return{hash:r,originalExt:t,originalPath:p,processedPaths:[x].filter(j=>j&&!j.endsWith(".scdn"))}}var Ae=f(require("fs"),1),bt=f(require("crypto"),1),ce=f(require("path"),1),At=require("terser");function Ps(e){return bt.default.createHash("sha256").update(e).digest("hex")}async function Fs(e){return(await(0,At.minify)(e,{compress:!1,mangle:{toplevel:!1},format:{comments:!1,semicolons:!0}})).code}function Ns(e){let o=e.split(`
60
+ `),t=o.reduce((r,n)=>r+n.length,0)/o.length,s=(e.match(/\s/g)?.length??0)/e.length;return t>200&&s<.15&&!/\/\*|\n\s*\/\//.test(e)}async function Pt(e){let o=Ae.default.readFileSync(e),t=ce.default.extname(e).replace(".","").toLowerCase(),s=ce.default.basename(e,ce.default.extname(e)),r=Ps(o);if(F(r),C(r,s,t))return{hash:r,originalExt:t,originalPath:E(r,s,t)};let a=Ae.default.readFileSync(e),i=a.toString("utf8"),l=a;if(!Ns(i)){let x=await Fs(i);l=Buffer.from(x)}let p=b(r,s,t,l);return{hash:r,originalExt:t,originalPath:p}}var Ft=f(require("fs"),1),Nt=f(require("crypto"),1),le=f(require("path"),1);function js(e){return Nt.default.createHash("sha256").update(e).digest("hex")}function Is(e){let o=(e.match(/\s/g)?.length??0)/e.length,t=e.split(`
61
+ `).length;return o<.08&&t<=2}function Os(e){let o=JSON.parse(e);return JSON.stringify(o)}async function jt(e){let o=Ft.default.readFileSync(e),t=le.default.extname(e).replace(".","").toLowerCase(),s=le.default.basename(e,le.default.extname(e)),r=js(o);if(F(r),C(r,s,t))return{hash:r,originalExt:t,originalPath:E(r,s,t)};let a=o.toString("utf8"),i=o;if(!Is(a)){let p=Os(a);i=Buffer.from(p)}if(!i||i.length===0)throw new Error("JSON minification produced empty output");let c=b(r,s,t,i);return{hash:r,originalExt:t,originalPath:c}}var It=f(require("fs"),1),Ot=f(require("crypto"),1),fe=f(require("path"),1),Lt=require("svgo");function Ls(e){return Ot.default.createHash("sha256").update(e).digest("hex")}function _s(e){let o=(e.match(/\s/g)?.length??0)/e.length,t=/<!--/.test(e),s=e.split(`
62
+ `).length;return o<.1&&s<=2&&!t}function Ts(e){let o=console.warn,t=console.info;console.warn=()=>{},console.info=()=>{};let s;try{s=(0,Lt.optimize)(e,{multipass:!0,plugins:[{name:"preset-default",params:{overrides:{convertPathData:!1,convertStyleToAttrs:!1,cleanupIds:!1,removeViewBox:!1,inlineStyles:!1}}},"removeUselessStrokeAndFill"]})}finally{console.warn=o,console.info=t}if(!("data"in s)||!s.data)throw new Error("SVG optimization failed");return s.data}async function _t(e){let o=It.default.readFileSync(e),s=fe.default.parse(e).ext.replace(".","").toLowerCase(),r=fe.default.basename(e,fe.default.extname(e)),n=Ls(o);if(F(n),C(n,r,s))return{hash:n,originalExt:s,originalPath:E(n,r,s)};let i=o.toString("utf8"),l=o;if(!_s(i)){let x=Ts(i);l=Buffer.from(x)}let p=b(n,r,s,l);return{hash:n,originalExt:s,originalPath:p}}var Fe=async({force:e=!1,sync:o=!1})=>{let t=await v(),s=w();if(!s){u("No .scdn.json found.");return}let r=!1;if(!s.projectId)u('Missing projectId in config file. Please run "scdn init" or "scdn load" command first.');else try{let n=await t.get("/status"),{plan:a,slug:i}=n.data;s.plan!==a&&(s.plan=a,P(s)),s.userSlug!==i&&(s.userSlug=i,P(s)),d(`Deploying assets${s.version?` for version ${s.version}`:""}...`);let l=await D(s.sources,s.excludes),c=await D(s.protected),p=[];if(l.length>0){let x=y("Deploying asset"),j=0;for(let m of l)if(++j,r&&!e)g(`Selected version was already published "${m}"`,x);else try{let $=Pe.default.basename(m),me=m.replace($,"").replace(/^\/+|\/+$/g,""),[,...ts]=me.split("/"),Ne=ts.join("/"),G=0;try{G=q.default.statSync(m).size}catch{throw new Error(`Cannot read file: ${m}`)}let je=re(s.plan||0,$,G);if(je!==!0)throw new Error(je);let _=$.split(".").pop()?.toLowerCase()??"",A;if(M.includes(_)&&_!=="avif")A=await st(m);else if(_==="js"||_==="mjs")A=await Pt(m);else if(_==="css")A=await wt(m);else if(_==="json")A=await jt(m);else if(_==="svg")A=await _t(m);else if(k.includes(_))A=await $t(m);else if(L.includes(_)){if(A=await dt(m),A===!1)throw new Error("To optimize audio - ffmpeg is required. Install it from https://ffmpeg.org/");if(A?.originalPath){try{G=q.default.statSync(A.originalPath).size}catch{throw new Error(`Cannot read file: ${A.originalPath}`)}let R=ct(s.plan||0,Pe.default.basename(A.originalPath),G);if(R!==!0)throw new Error(R)}else throw new Error("Audio was not optimized")}else te.includes(_)&&(A={originalPath:m,processedPaths:[]});let T=new Bt.default;T.append("asset",q.default.createReadStream(A?.originalPath?A.originalPath:m)),A?.processedPaths?.forEach(R=>{T.append("sub_assets[]",q.default.createReadStream(R))}),T.append("path",Ne),T.append("version",s.version||""),T.append("optimize",0),T.append("failIfExist",0),T.append("protected",c.includes(m)?1:0),e&&T.append("force",1),p.push({fileName:$,path:Ne});let W=await t.post(`/projects/${s.projectId}/assets`,T,{headers:T.getHeaders()});W.status===201?h(`Deployed "${m}"`,x):W.status===200&&(W.data?.error==="Cannot deploy/override assets on published version"?(r=!0,g(`Failed to deploy ${m}`,x,W)):W.data?.dedupe&&h(`Asset already exists "${m}"`,x))}catch($){g(`Failed to deploy ${m}`,x,$)}if(o){let m=y("Sync...");try{let $=await t.post(`/projects/${s.projectId}/assets/sync`,{force:e,version:s.version,assetsToSync:p});h(`Sync: ${$?.data?.removed??0} files removed`,m)}catch($){g($,m)}}}else u("No assets to deploy")}catch(n){u("Cannot proceed with pushing assets",n)}d("")},kt=new Tt.Command("push").option("--force","Override assets on published versions too").option("--sync","Additionally removes files that do not exists in project anymore").description("Push assets to CDN").action(Fe);var Dt=new Mt.Command("init").description("Initialize new project").action(async()=>{let e=await v(),o=!1;if(Q())d("Detected .scdn.json config file");else{let t=await(0,N.input)({message:"Project name:"});o=await(0,N.confirm)({message:"Enable versioning:",default:!1});let s=o?await(0,N.input)({message:"Initial version:",default:"1.0.0"}):"",r=await(0,N.confirm)({message:"Block bots for this variant?",default:!1}),n=await(0,N.confirm)({message:"Block headless browsers?",default:!1}),a=[],i=!0;for(;i;){let m=await(0,N.input)({message:"Add source path/pattern (glob allowed):",validate:B=>B.trim().length>0||"Source required"});a.push(m.trim()),i=await(0,N.confirm)({message:"Add another source?",default:!1})}let l=[];if(await(0,N.confirm)({message:"Add exclude patterns?",default:!1})){let m=!0;for(;m;){let $=await(0,N.input)({message:"Exclude path/pattern:",validate:B=>B.trim().length>0||"Exclude required"});l.push($.trim()),m=await(0,N.confirm)({message:"Add another exclude?",default:!1})}}let p=[];if(await(0,N.confirm)({message:"Add protected patterns?",default:!1})){let m=!0;for(;m;){let $=await(0,N.input)({message:"Protected path/pattern:",validate:B=>B.trim().length>0||"Protected required"});p.push($.trim()),m=await(0,N.confirm)({message:"Add another protected?",default:!1})}}let j={project:t,projectSlug:ze(t),version:s,blockBots:r,blockHeadless:n,sources:a,excludes:l,protected:p};P(j),d("Created .scdn.json config file")}if(Q()){d("Sending to Smooth CDN...");let t=w(),s,r=y(`Creating project "${t.project}"`);try{s=await e.post("/projects",{name:t.project,slug:t.projectSlug||"",withVersioning:o||!!t?.version,version:o||t?.version?t.version:"",block_bots:t.blockBots,block_headless:t.blockHeadless,sources:t?.sources||[],excludes:t?.excludes||[],protected:t?.protected||[],failIfExist:!1}),s.status===201?h(`Created new project "${t.project} ${t.version}"`,r):s.status===200&&h(`Project exist "${t.project} ${t.version}"`,r),s.data.id&&s.data.id!==t.projectId&&(t.projectId=s.data.id,P(t)),await Fe({force:!1}),d("Sent to Smooth CDN")}catch(n){g("Cannot create project",r,n)}}});var zt=require("commander"),Vt=f(require("fs"),1),Wt=f(require("path"),1);var Rt=new zt.Command("inspect-assets").description("Validates assets paths and lists assets for deployments").action(async()=>{let e=w();if(!e){u("No .scdn.json found.");return}d("Checking paths"),e?.sources?.forEach(t=>{let s=$e(t);s?O(t):u(`${t} [${s}]`)}),e?.excludes?.forEach(t=>{let s=$e(t);s?O(t):u(`${t} [${s}]`)}),d("Checking assets:");let o=await D(e.sources,e.excludes);o.length===0?u("No assets found"):o.forEach(t=>{let s=Wt.default.basename(t),r=0;try{r=Vt.default.statSync(t).size}catch{throw new Error(`Cannot read file: ${t}`)}let n=re(e.plan||0,s,r);n===!0?O(s):u(`${s} [${n}]`)}),d("")});var Ht=require("commander"),Xt=require("@inquirer/prompts");var Ut=new Ht.Command("load").description("Initialize project that already exists").action(async()=>{let e=w();if(e?.project&&e?.projectSlug)O("Project already initiated in .scdn config file.");else{let o=y("Fetching available projects...");try{let s=await(await v()).get("/projects?full=1");if(s.data.length>0){h(`${s.data.length} projects available`,o);let r=await(0,Xt.select)({message:"Which project to load:",choices:s.data.map(a=>({name:a.name,value:a.id}))}),n=s.data.find(a=>a.id===r);P({...e,project:n.name,projectId:n.id,projectSlug:n.slug,customSubdomain:n?.customSubdomain||"",version:n.withVersioning?n.latestVersion||n?.versions[0]?.version||"1.0.0":"",blockBots:!!n.blockBots,blockHeadless:!!n.blockHeadless,sources:n?.sources?JSON.parse(n.sources):[],excludes:n?.excludes?JSON.parse(n.excludes):[],protected:n?.protected?JSON.parse(n.protected):[]}),O("Config file saved")}else g("No projects available to be loaded from Smooth CDN",o)}catch(t){g("Failed to fetch projects",o,t)}}});var Jt=require("commander");var qt=new Jt.Command("publish-version").description("Publish selected version").argument("[version]","Version number, e.g. 1.0.0").action(async(e="")=>{let o=await v(),t=w();if(!t){u("No .scdn.json found.");return}let s=e||t.version;if(s){let r=y(`Publishing version "${s}"`);try{let n=await o.post(`/projects/${t.projectId}/versions/publish`,{version:s});n.status===201?h(`Published new version "${s}"`,r):n.status===200&&h(`Version already published "${s}"`,r)}catch(n){g(`Cannot publish version ${s}`,r,n)}}else u('Missing version. Please run "scdn create-version <version>" first.')});var Gt=require("commander"),pe=require("@inquirer/prompts");var Kt=new Gt.Command("revoke-access").description("Revoke access for smooth resources").action(async()=>{let e=await v(),o=w();if(!o){u("No .scdn.json found.");return}let t=await(0,pe.input)({message:"Enter user email to revoke access (mail@example.com):",validate:s=>oe(s)?!0:"Invalid mail format"});try{let s=y("Revoking access..."),r=await e.post("/customer/accesses",{email:t});r.data?.length<=0&&g(`No accesses found for "${t}"`,s),h(`Fetched ${r.data.length} accesses`,s);let n=await(0,pe.select)({message:"What access to revoke:",choices:r.data.map(l=>({name:`${l.project} (${l.assets.join(",")})`,value:l.id}))}),a=y("Revoking access..."),i=await e.post(`/projects/${o.projectId}/accesses/${n}/revoke`);i.status===201?h("Selected access revoked",a):i.status===200?h("Selected access already revoked",a):g("Failed to revoke access",a)}catch(s){u("Failed to revoke access",s)}});var Zt=require("commander");var Bs=["FREE","PRO","PREMIUM"],Qt=new Zt.Command("status").description("Get a status summary").action(async()=>{let e=await v(),o=await w();if(!o){u("No .scdn.json found.");return}let t,s=y("Fetching status...");try{t=await e.get("/status"),h("Fetched",s);try{let{name:r,email:n,plan:a,slug:i,planExpiration:l,limits:c,usage:p,projects:x=[]}=t.data;o.plan!==a&&(o.plan=a,P(o)),o.userSlug!==i&&(o.userSlug=i,P(o)),d(`Logged in as ${r} (${i} - ${n})`),d(`Plan: ${Bs[a]} ${l?`(Expires at ${he(l)})`:""}`),p&&(d("Usage limits:"),d(` Requests: ${H(p.requests)}/${H(p.maxRequests)}`),d(` Bandwidth: ${xe(p.bandwidth)}/${xe(p.maxBandwidth)}`),p.periodEnd&&d(` Resets at: ${he(p.periodEnd)}`)),d(""),d(`Projects (used projects: ${x.length}/${c.projects}):`),x.map((j,m)=>{d(` ${m+1}. ${j.name} (used assets: ${H(j.assetsCount)}/${H(c.assetsPerProject)})`)})}catch(r){g("Failed to parse status",s,r)}}catch(r){g("Failed to parse status",s,r)}});var es=require("module"),Ds={},ks=(0,es.createRequire)(Ds.url),Ms=ks("../package.json"),I=new Yt.Command;I.name("scdn").description("Smooth CDN CLI").version(Ms.version);I.addCommand(Re);I.addCommand(it);I.addCommand(ft);I.addCommand(Dt);I.addCommand(Rt);I.addCommand(Ut);I.addCommand(Ue);I.addCommand(qe);I.addCommand(qt);I.addCommand(kt);I.addCommand(Kt);I.addCommand(Qt);I.parse();
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{Command as Is}from"commander";import{Command as ut}from"commander";import ft from"axios";import te from"keytar";var se="smoothcdn",oe="cli_token";async function Ae(e){await te.setPassword(se,oe,e)}async function Pe(){return process.env.SCDN_TOKEN||te.getPassword(se,oe)}async function Fe(){await te.deletePassword(se,oe)}async function y(){let e=await Pe();return ft.create({baseURL:"https://smoothcdn.com/api",headers:e?{Authorization:`Bearer ${e}`}:{}})}import{confirm as gt}from"@inquirer/prompts";import re from"fs";import pt from"path";function ne(e=process.cwd()){return pt.join(e,".scdn.json")}function J(){return re.existsSync(ne())}function x(){return J()?JSON.parse(re.readFileSync(ne(),"utf8")):{}}function b(e){re.writeFileSync(ne(),JSON.stringify(e,null,2))}import ie from"ora";import{formatDate as mt}from"date-fns";import{enUS as dt}from"date-fns/locale";var Ne=(e,o)=>{let t,s;return o&&(t=o?.status||o?.code,s=o?.response?.data?.error||o?.data?.error||o?.message),`${e}${t?` [${t}]`:""}${s?` [${s}]`:""}`},m=e=>{console.log(e)},N=e=>{ie(e).succeed()},d=(e,o)=>{ie(Ne(e,o)).fail()},w=e=>ie(e).start(),g=(e,o)=>{o.succeed(e)},u=(e,o,t)=>{o.fail(Ne(e,t))};function ae(e){return typeof e=="string"&&(e=new Date(e)),mt(e,"dd MMMM yyyy HH:mm:ss",{locale:dt})}function ce(e,o=2){if(!e||e===0)return"0 B";let t=1024,s=o<0?0:o,r=["B","KB","MB","GB","TB"],n=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,n)).toFixed(s))+" "+r[n]}function R(e){if(e==null)return"0";let o=Math.abs(e);return o<1e3?e.toString():o<1e6?(e/1e3).toFixed(e%1e3===0?0:1)+"k":o<1e9?(e/1e6).toFixed(e%1e6===0?0:1)+"M":(e/1e9).toFixed(e%1e9===0?0:1)+"B"}var je=new ut("create-version").description("Create version for next deployments").argument("[version]","Version number, e.g. 1.0.0").action(async(e="")=>{let o=await y(),t=x();if(!t){d("No .scdn.json found.");return}let s=e||t.version,r=await gt({message:"Create version as blank (no assets will be copied from previous version automatically) ?",default:!1});if(s){let n=w(`Creating version "${s}"`);try{let a=await o.post(`/projects/${t.projectId}/versions`,{version:s,blank:r,failIfExist:!1});a.status===201?g(`Created new version "${s}"`,n):a.status===200&&g(`Version exist "${s}"`,n),e&&(t.version=e,b(t),m(".scdn.json config file updated"),N(`Using version ${e}`))}catch(a){u(`Cannot create version ${e}`,n,a)}}else d('Missing version. Please run "scdn create-version <version>" first.')});import{Command as ht}from"commander";import le from"os";import xt from"open";var Ie=new ht("login").description("Authenticate via browser").action(async()=>{let e=await y(),o=w("Starting login..."),t=[];try{let s=le.userInfo();s.username&&t.push(s.username)}catch{}try{let s=le.platform();s&&t.push(s)}catch{}try{let s=le.machine();s&&t.push(s)}catch{}try{let{data:s}=await e.post("/auth/cli",{label:t.join("-")}),{key_id:r,verification_url:n}=s;await xt(n),o.text="Waiting for authentication...";let a=null;for(;!a;){await new Promise(F=>setTimeout(F,1500));let f=await e.post("/auth/cli/poll",{keyId:r}).catch(()=>null);if(!f?.data)continue;let{status:h}=f.data;if(h!=="pending"){if(h==="expired"){u("Login session expired. Try again.",o);return}if(h==="active"){a=f.data.api_key;break}if(h==="already_active"){u("This login session is already used.",o);return}}}await Ae(a);let i=x(),c=await(await y()).get("/status");c.data&&(i.userSlug=c.data?.slug||"",c.data?.plan>=0&&i?.plan!==c.data?.plan&&(i.plan=c.data.plan),b(i)),g("Login successful!",o)}catch{u("There was an error when authorizing",o)}});import{Command as wt}from"commander";var Oe=new wt("logout").description("Remove credential data").action(async()=>{await Fe(),N("Successfully logged out")});import{Command as Lt}from"commander";import{confirm as B,input as D,select as ze}from"@inquirer/prompts";import _t from"clipboardy";import{globby as Le}from"globby";async function M(e=[],o=[]){let t=await Le(e,{dot:!0});if(o.length===0)return t;let s=await Le(o,{dot:!0});return t.filter(r=>!s.includes(r))}var _e=["js","mjs","css","json","svg","txt","csv","xml","md"],_=["woff2","woff","ttf","otf"],T=["png","jpg","jpeg","webp","avif"],j=["wav","aiff","aif","flac","mp3","ogg","oga","m4a","aac"],q=["pdf","doc","docx","xls","xlsx","ppt","pptx","odt","ods","odp"],Te=["json","txt","csv","xml","md","doc","docx","xls","xlsx","ppt","pptx","odt","ods","odp"],fe={0:{projects:1,assetsPerProject:50,bandwidth:1073741824,maxRequests:2e4,maxTextAssetSize:204800,maxImageAssetSize:2097152,maxAudioAssetSize:2097152,usageEventsMaxDays:3,usageEventsMaxAmount:100},1:{projects:10,assetsPerProject:1e4,bandwidth:107374182400,maxRequests:5e6,maxTextAssetSize:512e3,maxImageAssetSize:20971520,maxAudioAssetSize:52428800,usageEventsMaxDays:7,usageEventsMaxAmount:500},2:{projects:50,assetsPerProject:1e5,bandwidth:1099511627776,maxRequests:5e7,maxTextAssetSize:1048576,maxImageAssetSize:52428800,maxAudioAssetSize:104857600,usageEventsMaxDays:14,usageEventsMaxAmount:1e3}};var yt=({url:e,alt:o="",critical:t=!1,width:s,height:r})=>`<img
2
+ import{Command as Os}from"commander";import{Command as gt}from"commander";import pt from"axios";import te from"keytar";var se="smoothcdn",oe="cli_token";async function Ae(e){await te.setPassword(se,oe,e)}async function Pe(){return process.env.SCDN_TOKEN||te.getPassword(se,oe)}async function Fe(){await te.deletePassword(se,oe)}async function y(){let e=await Pe();return pt.create({baseURL:"https://smoothcdn.com/api",headers:e?{Authorization:`Bearer ${e}`}:{}})}import{confirm as ht}from"@inquirer/prompts";import re from"fs";import mt from"path";function ne(e=process.cwd()){return mt.join(e,".scdn.json")}function J(){return re.existsSync(ne())}function x(){return J()?JSON.parse(re.readFileSync(ne(),"utf8")):{}}function b(e){re.writeFileSync(ne(),JSON.stringify(e,null,2))}import ie from"ora";import{formatDate as dt}from"date-fns";import{enUS as ut}from"date-fns/locale";var Ne=(e,o)=>{let t,s;return o&&(t=o?.status||o?.code,s=o?.response?.data?.error||o?.data?.error||o?.message),`${e}${t?` [${t}]`:""}${s?` [${s}]`:""}`},m=e=>{console.log(e)},N=e=>{ie(e).succeed()},d=(e,o)=>{ie(Ne(e,o)).fail()},w=e=>ie(e).start(),g=(e,o)=>{o.succeed(e)},u=(e,o,t)=>{o.fail(Ne(e,t))};function ae(e){return typeof e=="string"&&(e=new Date(e)),dt(e,"dd MMMM yyyy HH:mm:ss",{locale:ut})}function ce(e,o=2){if(!e||e===0)return"0 B";let t=1024,s=o<0?0:o,r=["B","KB","MB","GB","TB"],n=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,n)).toFixed(s))+" "+r[n]}function R(e){if(e==null)return"0";let o=Math.abs(e);return o<1e3?e.toString():o<1e6?(e/1e3).toFixed(e%1e3===0?0:1)+"k":o<1e9?(e/1e6).toFixed(e%1e6===0?0:1)+"M":(e/1e9).toFixed(e%1e9===0?0:1)+"B"}function je(e){return e.toLowerCase().normalize("NFKD").trim().replace(/[\u0300-\u036f]/g,"").replace(/\s+/g,"-").replace(/[^a-z0-9\-]/g,"").replace(/\-+/g,"-")}var Ie=new gt("create-version").description("Create version for next deployments").argument("[version]","Version number, e.g. 1.0.0").action(async(e="")=>{let o=await y(),t=x();if(!t){d("No .scdn.json found.");return}let s=e||t.version,r=await ht({message:"Create version as blank (no assets will be copied from previous version automatically) ?",default:!1});if(s){let n=w(`Creating version "${s}"`);try{let a=await o.post(`/projects/${t.projectId}/versions`,{version:s,blank:r,failIfExist:!1});a.status===201?g(`Created new version "${s}"`,n):a.status===200&&g(`Version exist "${s}"`,n),e&&(t.version=e,b(t),m(".scdn.json config file updated"),N(`Using version ${e}`))}catch(a){u(`Cannot create version ${e}`,n,a)}}else d('Missing version. Please run "scdn create-version <version>" first.')});import{Command as xt}from"commander";import le from"os";import wt from"open";var Oe=new xt("login").description("Authenticate via browser").action(async()=>{let e=await y(),o=w("Starting login..."),t=[];try{let s=le.userInfo();s.username&&t.push(s.username)}catch{}try{let s=le.platform();s&&t.push(s)}catch{}try{let s=le.machine();s&&t.push(s)}catch{}try{let{data:s}=await e.post("/auth/cli",{label:t.join("-")}),{key_id:r,verification_url:n}=s;await wt(n),o.text="Waiting for authentication...";let a=null;for(;!a;){await new Promise(P=>setTimeout(P,1500));let f=await e.post("/auth/cli/poll",{keyId:r}).catch(()=>null);if(!f?.data)continue;let{status:h}=f.data;if(h!=="pending"){if(h==="expired"){u("Login session expired. Try again.",o);return}if(h==="active"){a=f.data.api_key;break}if(h==="already_active"){u("This login session is already used.",o);return}}}await Ae(a);let i=x(),c=await(await y()).get("/status");c.data&&(i.userSlug=c.data?.slug||"",c.data?.plan>=0&&i?.plan!==c.data?.plan&&(i.plan=c.data.plan),b(i)),g("Login successful!",o)}catch{u("There was an error when authorizing",o)}});import{Command as yt}from"commander";var Le=new yt("logout").description("Remove credential data").action(async()=>{await Fe(),N("Successfully logged out")});import{Command as _t}from"commander";import{confirm as B,input as D,select as Ve}from"@inquirer/prompts";import Tt from"clipboardy";import{globby as _e}from"globby";async function M(e=[],o=[]){let t=await _e(e,{dot:!0});if(o.length===0)return t;let s=await _e(o,{dot:!0});return t.filter(r=>!s.includes(r))}var Te=["js","mjs","css","json","svg","txt","csv","xml","md"],_=["woff2","woff","ttf","otf"],T=["png","jpg","jpeg","webp","avif"],j=["wav","aiff","aif","flac","mp3","ogg","oga","m4a","aac"],q=["pdf","doc","docx","xls","xlsx","ppt","pptx","odt","ods","odp"],Be=["json","txt","csv","xml","md","doc","docx","xls","xlsx","ppt","pptx","odt","ods","odp"],fe={0:{projects:1,assetsPerProject:50,bandwidth:1073741824,maxRequests:2e4,maxTextAssetSize:204800,maxImageAssetSize:2097152,maxAudioAssetSize:2097152,usageEventsMaxDays:3,usageEventsMaxAmount:100},1:{projects:10,assetsPerProject:1e4,bandwidth:107374182400,maxRequests:5e6,maxTextAssetSize:512e3,maxImageAssetSize:20971520,maxAudioAssetSize:52428800,usageEventsMaxDays:7,usageEventsMaxAmount:500},2:{projects:50,assetsPerProject:1e5,bandwidth:1099511627776,maxRequests:5e7,maxTextAssetSize:1048576,maxImageAssetSize:52428800,maxAudioAssetSize:104857600,usageEventsMaxDays:14,usageEventsMaxAmount:1e3}};var St=({url:e,alt:o="",critical:t=!1,width:s,height:r})=>`<img
3
3
  src="${e}"
4
4
  alt="${o}"${t?`
5
5
  fetchpriority="high"
@@ -8,7 +8,7 @@ import{Command as Is}from"commander";import{Command as ut}from"commander";import
8
8
  decoding="async"`}${s?`
9
9
  width="${s}"`:""}${r?`
10
10
  height="${r}"`:""}
11
- />`,St=({url:e,scriptType:o="standard"})=>{switch(o){case"critical":return`<link
11
+ />`,vt=({url:e,scriptType:o="standard"})=>{switch(o){case"critical":return`<link
12
12
  rel="preload"
13
13
  as="script"
14
14
  href="${e}"
@@ -22,7 +22,7 @@ import{Command as Is}from"commander";import{Command as ut}from"commander";import
22
22
  ></script>`;default:return`<script
23
23
  src="${e}"
24
24
  defer
25
- ></script>`}},vt=({url:e,preload:o=!1})=>o?`<link
25
+ ></script>`}},Et=({url:e,preload:o=!1})=>o?`<link
26
26
  rel="preload"
27
27
  as="style"
28
28
  href="${e}"
@@ -33,30 +33,30 @@ import{Command as Is}from"commander";import{Command as ut}from"commander";import
33
33
  />`:`<link
34
34
  rel="stylesheet"
35
35
  href="${e}"
36
- />`,Et=({url:e,controls:o=!1,loop:t=!1,preload:s="none"})=>`<audio
36
+ />`,Ct=({url:e,controls:o=!1,loop:t=!1,preload:s="none"})=>`<audio
37
37
  src="${e}"${s?`
38
38
  preload="${s}"`:""}${o?`
39
39
  controls`:""}${t?`
40
40
  loop`:""}
41
- ></audio>`,Ct=({url:e,extension:o,fontFamily:t="",fontDisplay:s="swap"})=>`<style>
41
+ ></audio>`,$t=({url:e,extension:o,fontFamily:t="",fontDisplay:s="swap"})=>`<style>
42
42
  @font-face {
43
43
  font-family: "${t}";
44
44
  src: url("${e}") format("${o}");
45
45
  font-display: ${s};
46
46
  }
47
- </style>`,$t=({url:e,lazy:o=!1,title:t="",width:s="",height:r=""})=>`<iframe
47
+ </style>`,bt=({url:e,lazy:o=!1,title:t="",width:s="",height:r=""})=>`<iframe
48
48
  src="${e}"${o?`
49
49
  loading="lazy"`:""}${t?`
50
50
  title="${t}`:""}${s?`
51
51
  width="${s}"`:""}${r?`
52
52
  height="${r}"`:""}
53
- ></iframe>`,bt=({url:e,assetName:o,newTab:t=!0,download:s=!0,noreferrer:r=!1})=>{let n=[];t&&n.push("noopener"),r&&n.push("noreferrer");let a=n.length?n.join(" "):"";return`<a
53
+ ></iframe>`,At=({url:e,assetName:o,newTab:t=!0,download:s=!0,noreferrer:r=!1})=>{let n=[];t&&n.push("noopener"),r&&n.push("noreferrer");let a=n.length?n.join(" "):"";return`<a
54
54
  href="${e}"${t?`
55
55
  target="_blank"`:""}${a?`
56
56
  rel="${a}"`:""}${s?`
57
57
  download`:""}
58
- >Download ${o}</a>`};function Be(e={}){let{extension:o}=e;return o==="js"||o==="mjs"?St(e):o==="css"?vt(e):o==="pdf"?$t(e):o==="svg"||T.includes(o)?yt(e):j.includes(o)?Et(e):_.includes(o)?Ct(e):bt(e)}import ge from"fs";import Nt from"crypto";import K from"path";import{imageSize as jt}from"image-size";import{XMLParser as It}from"fast-xml-parser";import z from"fs";import H from"path";var pe=H.resolve(".scdn");function At(){z.existsSync(pe)||z.mkdirSync(pe,{recursive:!0})}function me(e){return At(),H.join(pe,e)}function A(e){let o=me(e);return z.existsSync(o)||z.mkdirSync(o,{recursive:!0}),o}function C(e,o,t,s){let r=A(e),n=H.join(r,`${o}.${t}`);return z.writeFileSync(n,s),n}function v(e,o,t){let s=H.join(me(e),`${o}.${t}`);return z.existsSync(s)}function S(e,o,t){return H.join(me(e),`${o}.${t}`)}import G from"sharp";async function Pt(e){return G(e).png({compressionLevel:9,quality:70,adaptiveFiltering:!0,palette:!0,dither:.5,effort:8}).toBuffer()}async function Ft(e){return G(e).jpeg({quality:70,chromaSubsampling:"4:2:0",mozjpeg:!0}).toBuffer()}async function de(e,o={}){let t=o.quality??80;return G(e).webp({quality:t,effort:6}).toBuffer()}async function ue(e,o={}){let t=o.quality??50;return G(e).avif({quality:t,speed:4}).toBuffer()}async function ke(e,o){let t=o.toLowerCase();return t==="png"?Pt(e):t==="jpg"||t==="jpeg"?Ft(e):t==="webp"?de(e):t==="avif"?ue(e):e}function Ot(e){return Nt.createHash("sha256").update(e).digest("hex")}async function Me(e){let o=ge.readFileSync(e),t=K.extname(e).replace(".","").toLowerCase(),s=K.basename(e,K.extname(e)),r=Ot(o);A(r);let n=v(r,s,t),a=v(r,s,"webp"),i=v(r,s,"avif"),l=t==="webp",c=t==="avif";if(n&&(l||a)&&(c||i))return{hash:r,originalExt:t,originalPath:S(r,s,t),processedPaths:[!l&&a?S(r,s,"webp"):null,!c&&i?S(r,s,"avif"):null].filter(Boolean)};let f=await ke(o,t),h=l?null:await de(o),F=c?null:await ue(o),p=C(r,s,t,f),E=!l&&h?C(r,s,"webp",h):null,L=!c&&F?C(r,s,"avif",F):null;return{hash:r,originalExt:t,originalPath:p,processedPaths:[E,L].filter(ee=>!ee?.endsWith(".scdn"))}}function De(e){if(K.extname(e).toLowerCase().replace(".","")==="svg"){let r=ge.readFileSync(e,"utf-8"),i=new It({ignoreAttributes:!1}).parse(r)?.svg;if(!i)return null;if(i["@_width"]&&i["@_height"])return{width:parseFloat(i["@_width"]),height:parseFloat(i["@_height"])};if(i["@_viewBox"]){let[,,l,c]=i["@_viewBox"].split(/\s+/).map(Number);if(l&&c)return{width:l,height:c}}return null}let t=ge.readFileSync(e),s=jt(t);return!s.width||!s.height?null:{width:s.width,height:s.height}}function Tt(e,o,t,s,r=""){return t?`https://${t}.smoothcdn.com${r?`/${r}`:""}${s}`:`https://cdn.smoothcdn.com/${e}/${o}${r?`/${r}`:""}${s}`}var Ve=new Lt("get-snippet").description("Output snippet for asset").action(async()=>{let e=x();if(!e){d("No .scdn.json found.");return}let o=await M(e.sources,e.excludes);if(o.length<=0){d("No assets found");return}m(`Found assets ${o.length}`);let t=await ze({message:"What asset to get snippet for:",choices:o.map(c=>({name:c,value:c}))}),[,...s]=t.split("/"),r=`/${s.join("/")}`,n=t.split(".").pop()?.toLowerCase()??"",a=Tt(e.userSlug,e.projectSlug,e.customSubdomain||"",r,e.version||""),i={extension:n,url:a,assetName:t};if(n==="svg"||T.includes(n)){let c=await De(t);i.alt=await D({message:"Alt attribute",validate:f=>f?!0:"Alt attribute is required",default:t}),i.critical=await B({message:"Is critical asset (must be loaded above the fold e.g. in hero section)"}),i.width=await D({message:"Width",default:c?.width?.toString()||""}),i.height=await D({message:"Height",default:c?.height?.toString()||""})}(n==="js"||n==="mjs")&&(i.type=await ze({message:"Script type",choices:[{name:"Standard",value:"standard"},{name:"Critical",value:"critical"},{name:"Asynchronous",value:"async"}]})),n==="css"&&(i.preload=await B({message:"Preload"})),j.includes(n)&&(i.controls=await B({message:"Controls attribute (shows audio control buttons)"}),i.loop=await B({message:"Loop attribute (plays audio in loop)"})),_.includes(n)&&(i.fontFamily=await D({message:"Font family",default:t})),n==="pdf"&&(i.lazy=await B({message:"Lazy load"}),i.title=await D({message:"Title",default:t}),i.width=await D({message:"Width",default:"100%"}),i.height=await D({message:"Height",default:"600"})),Te.includes(n)&&(i.newTab=await B({message:"Open in new tab"}),i.noreferrer=await B({message:'Hide referrer (adds "noreferrer" to rel attribute)'}),i.download=await B({message:"Download attribute"}));let l=Be(i);await _t.write(l),m(""),m(l),m(""),N("Snippet was copied to clipboard")});import{Command as kt}from"commander";import{checkbox as Mt,input as Re}from"@inquirer/prompts";import Bt from"micromatch";function Z(e){if(!e)return!1;let o=e.trim();return o.length<6||o.length>254||o.includes("..")?!1:/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(o)}function Q(e=0,o,t){let{maxTextAssetSize:s,maxImageAssetSize:r}=fe[e],n=o.split(".").pop()?.toLowerCase()??"",a=_e.includes(n),i=_.includes(n),l=T.includes(n),c=j.includes(n),f=q.includes(n);return!a&&!i&&!l&&!c&&!f?`Unsupported file type: ${n}`:(a||i)&&t>s?`Asset too large. Max allowed ${Math.round(s/1024)} KB, trying to send ${Math.round(t/1024)} KB`:(l||f)&&t>r?`Asset too large. Max allowed ${Math.round(r/(1024*1024))} MB, trying to send ${(t/1024/1024).toFixed(2)} MB`:!0}function We(e=0,o,t){let{maxAudioAssetSize:s}=fe[e],r=o.split(".").pop()?.toLowerCase()??"";return j.includes(r)&&t>s?`Asset too large. Max allowed ${Math.round(s/(1024*1024))} MB, received ${(t/1024/1024).toFixed(2)} MB`:!0}function he(e){try{Bt.matcher(e)}catch{return"Invalid pattern"}return e.includes("\0")||e.includes("..")||e.includes("~")||e.startsWith("/")||/^[A-Za-z]:\\/.test(e)?"Contains invalid segments":!0}var He=new kt("grant-access").description("Grant access for smooth resources").option("--force","Override expiration date if access already exists").action(async({force:e=!1})=>{let o=await y(),t=x();if(!t){d("No .scdn.json found.");return}let r=((await o.get(`/projects/${t.projectId}/assets`)).data??[]).filter(n=>n.protected).map(n=>`${n.path}${n.fileName}`);if(r.length===0)d("No protected assets found");else{let n=await Mt({message:"Select protected assets to grant access to:",choices:r.map(c=>({name:c,value:c})),validate:c=>c.length>0?!0:"Select at least one asset."}),a=await Re({message:"Enter user email to grant access (mail@example.com):",validate:c=>Z(c)?!0:"Invalid mail format"}),i=await Re({message:"Enter expiration date (leave empty if no expiration should be set):"}),l=w("Granting access...");try{let c={force:e,assets:n,email:a,expiresAt:i},f=await o.post(`/projects/${t.projectId}/accesses/grant`,c);f.status===201?g(`Access granted for "${a}"`,l):f.status===200?g(`Access already exists for "${a}"`,l):u("Unexpected response from server",l,f)}catch(c){u("Failed to grant access",l,c)}}});import{Command as ys}from"commander";import{input as X,confirm as k}from"@inquirer/prompts";import{Command as xs}from"commander";import ws from"form-data";import Y from"fs";import tt from"path";import Dt from"fs";import zt from"crypto";import xe from"path";import{execFileSync as Xe}from"child_process";function Vt(e){return zt.createHash("sha256").update(e).digest("hex")}function Wt(){try{return Xe("ffmpeg",["-version"],{stdio:"ignore"}),!0}catch{return!1}}function Rt(e,o){Xe("ffmpeg",["-y","-i",e,"-map_metadata","-1","-vn","-c:a","aac","-q:a","2","-movflags","+faststart",o],{stdio:"ignore"})}async function Ue(e){if(!Wt())return!1;let o=Dt.readFileSync(e),t=xe.extname(e).replace(".","").toLowerCase(),s=xe.basename(e,xe.extname(e));if(!j.includes(t))throw new Error(`Unsupported audio extension: .${t}`);let r=Vt(o);A(r);let n=v(r,s,t),a=v(r,s,"m4a"),i=n?S(r,s,t):C(r,s,t,o);if(a)return{hash:r,originalExt:t,originalPath:i,processedPaths:[S(r,s,"m4a")]};let l=S(r,s,"m4a");return Rt(i,l),{hash:r,originalExt:t,originalPath:i,processedPaths:[l]}}import Ht from"fs";import Xt from"crypto";import we from"path";import Ut from"postcss";import Jt from"cssnano";function qt(e){return Xt.createHash("sha256").update(e).digest("hex")}function Gt(e){let o=e.split(`
59
- `),t=o.reduce((n,a)=>n+a.length,0)/o.length,s=(e.match(/\s/g)?.length??0)/e.length,r=/\/\*/.test(e);return t>200&&s<.12&&!r}async function Kt(e){return(await Ut([Jt({preset:["default",{discardComments:!0,normalizeWhitespace:!0,mergeRules:!1,mergeLonghand:!1,reduceIdents:!1,zindex:!1,calc:!1,colormin:!1,normalizeUrls:!1,normalizeTimingFunctions:!1,normalizeUnicode:!1,minifyFontValues:!1,minifySelectors:!1}]})]).process(e,{from:void 0})).css}async function Je(e){let o=Ht.readFileSync(e),t=we.extname(e).replace(".","").toLowerCase(),s=we.basename(e,we.extname(e)),r=qt(o);if(A(r),v(r,s,t))return{hash:r,originalExt:t,originalPath:S(r,s,t)};let a=o.toString("utf8"),i=o;if(!Gt(a)){let f=await Kt(a);i=Buffer.from(f)}let c=C(r,s,t,i);return{hash:r,originalExt:t,originalPath:c}}import Qt from"fs";import Yt from"crypto";import ye from"path";import Zt from"ttf2woff2";async function qe(e,o){return e}async function Ge(e){return Buffer.from(Zt(e))}function es(e){return Yt.createHash("sha256").update(e).digest("hex")}async function Ke(e){let o=Qt.readFileSync(e),t=ye.extname(e).replace(".","").toLowerCase(),s=ye.basename(e,ye.extname(e)),r=es(o);A(r);let n=v(r,s,t),a=v(r,s,"woff2"),i=t==="woff2";if(n&&(i||a))return{hash:r,originalExt:t,originalPath:S(r,s,t),processedPaths:[!i&&a?S(r,s,"woff2"):null].filter(Boolean)};let l=await qe(o,t),c=i?null:await Ge(o),f=C(r,s,t,l),h=!i&&c?C(r,s,"woff2",c):null;return{hash:r,originalExt:t,originalPath:f,processedPaths:[h].filter(F=>F&&!F.endsWith(".scdn"))}}import Ze from"fs";import ts from"crypto";import Se from"path";import{minify as ss}from"terser";function os(e){return ts.createHash("sha256").update(e).digest("hex")}async function rs(e){return(await ss(e,{compress:!1,mangle:{toplevel:!1},format:{comments:!1,semicolons:!0}})).code}function ns(e){let o=e.split(`
60
- `),t=o.reduce((r,n)=>r+n.length,0)/o.length,s=(e.match(/\s/g)?.length??0)/e.length;return t>200&&s<.15&&!/\/\*|\n\s*\/\//.test(e)}async function Qe(e){let o=Ze.readFileSync(e),t=Se.extname(e).replace(".","").toLowerCase(),s=Se.basename(e,Se.extname(e)),r=os(o);if(A(r),v(r,s,t))return{hash:r,originalExt:t,originalPath:S(r,s,t)};let a=Ze.readFileSync(e),i=a.toString("utf8"),l=a;if(!ns(i)){let h=await rs(i);l=Buffer.from(h)}let f=C(r,s,t,l);return{hash:r,originalExt:t,originalPath:f}}import is from"fs";import as from"crypto";import ve from"path";function cs(e){return as.createHash("sha256").update(e).digest("hex")}function ls(e){let o=(e.match(/\s/g)?.length??0)/e.length,t=e.split(`
61
- `).length;return o<.08&&t<=2}function fs(e){let o=JSON.parse(e);return JSON.stringify(o)}async function Ye(e){let o=is.readFileSync(e),t=ve.extname(e).replace(".","").toLowerCase(),s=ve.basename(e,ve.extname(e)),r=cs(o);if(A(r),v(r,s,t))return{hash:r,originalExt:t,originalPath:S(r,s,t)};let a=o.toString("utf8"),i=o;if(!ls(a)){let f=fs(a);i=Buffer.from(f)}if(!i||i.length===0)throw new Error("JSON minification produced empty output");let c=C(r,s,t,i);return{hash:r,originalExt:t,originalPath:c}}import ps from"fs";import ms from"crypto";import Ee from"path";import{optimize as ds}from"svgo";function us(e){return ms.createHash("sha256").update(e).digest("hex")}function gs(e){let o=(e.match(/\s/g)?.length??0)/e.length,t=/<!--/.test(e),s=e.split(`
62
- `).length;return o<.1&&s<=2&&!t}function hs(e){let o=console.warn,t=console.info;console.warn=()=>{},console.info=()=>{};let s;try{s=ds(e,{multipass:!0,plugins:[{name:"preset-default",params:{overrides:{convertPathData:!1,convertStyleToAttrs:!1,cleanupIds:!1,removeViewBox:!1,inlineStyles:!1}}},"removeUselessStrokeAndFill"]})}finally{console.warn=o,console.info=t}if(!("data"in s)||!s.data)throw new Error("SVG optimization failed");return s.data}async function et(e){let o=ps.readFileSync(e),s=Ee.parse(e).ext.replace(".","").toLowerCase(),r=Ee.basename(e,Ee.extname(e)),n=us(o);if(A(n),v(n,r,s))return{hash:n,originalExt:s,originalPath:S(n,r,s)};let i=o.toString("utf8"),l=o;if(!gs(i)){let h=hs(i);l=Buffer.from(h)}let f=C(n,r,s,l);return{hash:n,originalExt:s,originalPath:f}}var Ce=async({force:e=!1,sync:o=!1})=>{let t=await y(),s=x();if(!s){d("No .scdn.json found.");return}let r=!1;if(!s.projectId)d('Missing projectId in config file. Please run "scdn init" or "scdn load" command first.');else try{let n=await t.get("/status"),{plan:a,slug:i}=n.data;s.plan!==a&&(s.plan=a,b(s)),s.userSlug!==i&&(s.userSlug=i,b(s)),m(`Deploying assets${s.version?` for version ${s.version}`:""}...`);let l=await M(s.sources,s.excludes),c=await M(s.protected),f=[];if(l.length>0){let h=w("Deploying asset"),F=0;for(let p of l)if(++F,r&&!e)u(`Selected version was already published "${p}"`,h);else try{let E=tt.basename(p),ee=p.replace(E,"").replace(/^\/+|\/+$/g,""),[,...lt]=ee.split("/"),$e=lt.join("/"),U=0;try{U=Y.statSync(p).size}catch{throw new Error(`Cannot read file: ${p}`)}let be=Q(s.plan||0,E,U);if(be!==!0)throw new Error(be);let I=E.split(".").pop()?.toLowerCase()??"",$;if(T.includes(I)&&I!=="avif")$=await Me(p);else if(I==="js"||I==="mjs")$=await Qe(p);else if(I==="css")$=await Je(p);else if(I==="json")$=await Ye(p);else if(I==="svg")$=await et(p);else if(_.includes(I))$=await Ke(p);else if(j.includes(I)){if($=await Ue(p),$===!1)throw new Error("To optimize audio - ffmpeg is required. Install it from https://ffmpeg.org/");if($?.originalPath){try{U=Y.statSync($.originalPath).size}catch{throw new Error(`Cannot read file: ${$.originalPath}`)}let W=We(s.plan||0,tt.basename($.originalPath),U);if(W!==!0)throw new Error(W)}else throw new Error("Audio was not optimized")}else q.includes(I)&&($={originalPath:p,processedPaths:[]});let O=new ws;O.append("asset",Y.createReadStream($?.originalPath?$.originalPath:p)),$?.processedPaths?.forEach(W=>{O.append("sub_assets[]",Y.createReadStream(W))}),O.append("path",$e),O.append("version",s.version||""),O.append("optimize",0),O.append("failIfExist",0),O.append("protected",c.includes(p)?1:0),e&&O.append("force",1),f.push({fileName:E,path:$e});let V=await t.post(`/projects/${s.projectId}/assets`,O,{headers:O.getHeaders()});V.status===201?g(`Deployed "${p}"`,h):V.status===200&&(V.data?.error==="Cannot deploy/override assets on published version"?(r=!0,u(`Failed to deploy ${p}`,h,V)):V.data?.dedupe&&g(`Asset already exists "${p}"`,h))}catch(E){u(`Failed to deploy ${p}`,h,E)}if(o){let p=w("Sync...");try{let E=await t.post(`/projects/${s.projectId}/assets/sync`,{force:e,version:s.version,assetsToSync:f});g(`Sync: ${E?.data?.removed??0} files removed`,p)}catch(E){u(E,p)}}}else d("No assets to deploy")}catch(n){d("Cannot proceed with pushing assets",n)}m("")},st=new xs("push").option("--force","Override assets on published versions too").option("--sync","Additionally removes files that do not exists in project anymore").description("Push assets to CDN").action(Ce);var ot=new ys("init").description("Initialize new project").action(async()=>{let e=await y(),o=!1;if(J())m("Detected .scdn.json config file");else{let t=await X({message:"Project name:"});o=await k({message:"Enable versioning:",default:!1});let s=o?await X({message:"Initial version:",default:"1.0.0"}):"",r=await k({message:"Block bots for this variant?",default:!1}),n=await k({message:"Block headless browsers?",default:!1}),a=[],i=!0;for(;i;){let p=await X({message:"Add source path/pattern (glob allowed):",validate:L=>L.trim().length>0||"Source required"});a.push(p.trim()),i=await k({message:"Add another source?",default:!1})}let l=[];if(await k({message:"Add exclude patterns?",default:!1})){let p=!0;for(;p;){let E=await X({message:"Exclude path/pattern:",validate:L=>L.trim().length>0||"Exclude required"});l.push(E.trim()),p=await k({message:"Add another exclude?",default:!1})}}let f=[];if(await k({message:"Add protected patterns?",default:!1})){let p=!0;for(;p;){let E=await X({message:"Protected path/pattern:",validate:L=>L.trim().length>0||"Protected required"});f.push(E.trim()),p=await k({message:"Add another protected?",default:!1})}}b({project:t,version:s,blockBots:r,blockHeadless:n,sources:a,excludes:l,protected:f}),m("Created .scdn.json config file")}if(J()){m("Sending to Smooth CDN...");let t=x(),s,r=w(`Creating project "${t.project}"`);try{s=await e.post("/projects",{name:t.project,slug:t.projectSlug||"",withVersioning:o||!!t?.version,version:o||t?.version?t.version:"",block_bots:t.blockBots,block_headless:t.blockHeadless,sources:t?.sources||[],excludes:t?.excludes||[],protected:t?.protected||[],failIfExist:!1}),s.status===201?g(`Created new project "${t.project} ${t.version}"`,r):s.status===200&&g(`Project exist "${t.project} ${t.version}"`,r),s.data.id&&s.data.id!==t.projectId&&(t.projectId=s.data.id,b(t)),await Ce({force:!1}),m("Sent to Smooth CDN")}catch(n){u("Cannot create project",r,n)}}});import{Command as Ss}from"commander";import vs from"fs";import Es from"path";var rt=new Ss("inspect-assets").description("Validates assets paths and lists assets for deployments").action(async()=>{let e=x();if(!e){d("No .scdn.json found.");return}m("Checking paths"),e?.sources?.forEach(t=>{let s=he(t);s?N(t):d(`${t} [${s}]`)}),e?.excludes?.forEach(t=>{let s=he(t);s?N(t):d(`${t} [${s}]`)}),m("Checking assets:");let o=await M(e.sources,e.excludes);o.length===0?d("No assets found"):o.forEach(t=>{let s=Es.basename(t),r=0;try{r=vs.statSync(t).size}catch{throw new Error(`Cannot read file: ${t}`)}let n=Q(e.plan||0,s,r);n===!0?N(s):d(`${s} [${n}]`)}),m("")});import{Command as Cs}from"commander";import{select as $s}from"@inquirer/prompts";var nt=new Cs("load").description("Initialize project that already exists").action(async()=>{let e=x();if(e?.project&&e?.projectSlug)N("Project already initiated in .scdn config file.");else{let o=w("Fetching available projects...");try{let s=await(await y()).get("/projects?full=1");if(s.data.length>0){g(`${s.data.length} projects available`,o);let r=await $s({message:"Which project to load:",choices:s.data.map(a=>({name:a.name,value:a.id}))}),n=s.data.find(a=>a.id===r);b({...e,project:n.name,projectId:n.id,projectSlug:n.slug,customSubdomain:n?.customSubdomain||"",version:n.withVersioning?n.latestVersion||n?.versions[0]?.version||"1.0.0":"",blockBots:!!n.blockBots,blockHeadless:!!n.blockHeadless,sources:n?.sources?JSON.parse(n.sources):[],excludes:n?.excludes?JSON.parse(n.excludes):[],protected:n?.protected?JSON.parse(n.protected):[]}),N("Config file saved")}else u("No projects available to be loaded from Smooth CDN",o)}catch(t){u("Failed to fetch projects",o,t)}}});import{Command as bs}from"commander";var it=new bs("publish-version").description("Publish selected version").argument("[version]","Version number, e.g. 1.0.0").action(async(e="")=>{let o=await y(),t=x();if(!t){d("No .scdn.json found.");return}let s=e||t.version;if(s){let r=w(`Publishing version "${s}"`);try{let n=await o.post(`/projects/${t.projectId}/versions/publish`,{version:s});n.status===201?g(`Published new version "${s}"`,r):n.status===200&&g(`Version already published "${s}"`,r)}catch(n){u(`Cannot publish version ${s}`,r,n)}}else d('Missing version. Please run "scdn create-version <version>" first.')});import{Command as As}from"commander";import{input as Ps,select as Fs}from"@inquirer/prompts";var at=new As("revoke-access").description("Revoke access for smooth resources").action(async()=>{let e=await y(),o=x();if(!o){d("No .scdn.json found.");return}let t=await Ps({message:"Enter user email to revoke access (mail@example.com):",validate:s=>Z(s)?!0:"Invalid mail format"});try{let s=w("Revoking access..."),r=await e.post("/customer/accesses",{email:t});r.data?.length<=0&&u(`No accesses found for "${t}"`,s),g(`Fetched ${r.data.length} accesses`,s);let n=await Fs({message:"What access to revoke:",choices:r.data.map(l=>({name:`${l.project} (${l.assets.join(",")})`,value:l.id}))}),a=w("Revoking access..."),i=await e.post(`/projects/${o.projectId}/accesses/${n}/revoke`);i.status===201?g("Selected access revoked",a):i.status===200?g("Selected access already revoked",a):u("Failed to revoke access",a)}catch(s){d("Failed to revoke access",s)}});import{Command as Ns}from"commander";var js=["FREE","PRO","PREMIUM"],ct=new Ns("status").description("Get a status summary").action(async()=>{let e=await y(),o=await x();if(!o){d("No .scdn.json found.");return}let t,s=w("Fetching status...");try{t=await e.get("/status"),g("Fetched",s);try{let{name:r,email:n,plan:a,slug:i,planExpiration:l,limits:c,usage:f,projects:h=[]}=t.data;o.plan!==a&&(o.plan=a,b(o)),o.userSlug!==i&&(o.userSlug=i,b(o)),m(`Logged in as ${r} (${i} - ${n})`),m(`Plan: ${js[a]} ${l?`(Expires at ${ae(l)})`:""}`),f&&(m("Usage limits:"),m(` Requests: ${R(f.requests)}/${R(f.maxRequests)}`),m(` Bandwidth: ${ce(f.bandwidth)}/${ce(f.maxBandwidth)}`),f.periodEnd&&m(` Resets at: ${ae(f.periodEnd)}`)),m(""),m(`Projects (used projects: ${h.length}/${c.projects}):`),h.map((F,p)=>{m(` ${p+1}. ${F.name} (used assets: ${R(F.assetsCount)}/${R(c.assetsPerProject)})`)})}catch(r){u("Failed to parse status",s,r)}}catch(r){u("Failed to parse status",s,r)}});import{createRequire as Os}from"module";var Ls=Os(import.meta.url),_s=Ls("../package.json"),P=new Is;P.name("scdn").description("Smooth CDN CLI").version(_s.version);P.addCommand(je);P.addCommand(Ve);P.addCommand(He);P.addCommand(ot);P.addCommand(rt);P.addCommand(nt);P.addCommand(Ie);P.addCommand(Oe);P.addCommand(it);P.addCommand(st);P.addCommand(at);P.addCommand(ct);P.parse();
58
+ >Download ${o}</a>`};function ke(e={}){let{extension:o}=e;return o==="js"||o==="mjs"?vt(e):o==="css"?Et(e):o==="pdf"?bt(e):o==="svg"||T.includes(o)?St(e):j.includes(o)?Ct(e):_.includes(o)?$t(e):At(e)}import ge from"fs";import jt from"crypto";import K from"path";import{imageSize as It}from"image-size";import{XMLParser as Ot}from"fast-xml-parser";import z from"fs";import H from"path";var pe=H.resolve(".scdn");function Pt(){z.existsSync(pe)||z.mkdirSync(pe,{recursive:!0})}function me(e){return Pt(),H.join(pe,e)}function A(e){let o=me(e);return z.existsSync(o)||z.mkdirSync(o,{recursive:!0}),o}function C(e,o,t,s){let r=A(e),n=H.join(r,`${o}.${t}`);return z.writeFileSync(n,s),n}function v(e,o,t){let s=H.join(me(e),`${o}.${t}`);return z.existsSync(s)}function S(e,o,t){return H.join(me(e),`${o}.${t}`)}import G from"sharp";async function Ft(e){return G(e).png({compressionLevel:9,quality:70,adaptiveFiltering:!0,palette:!0,dither:.5,effort:8}).toBuffer()}async function Nt(e){return G(e).jpeg({quality:70,chromaSubsampling:"4:2:0",mozjpeg:!0}).toBuffer()}async function de(e,o={}){let t=o.quality??80;return G(e).webp({quality:t,effort:6}).toBuffer()}async function ue(e,o={}){let t=o.quality??50;return G(e).avif({quality:t,speed:4}).toBuffer()}async function Me(e,o){let t=o.toLowerCase();return t==="png"?Ft(e):t==="jpg"||t==="jpeg"?Nt(e):t==="webp"?de(e):t==="avif"?ue(e):e}function Lt(e){return jt.createHash("sha256").update(e).digest("hex")}async function De(e){let o=ge.readFileSync(e),t=K.extname(e).replace(".","").toLowerCase(),s=K.basename(e,K.extname(e)),r=Lt(o);A(r);let n=v(r,s,t),a=v(r,s,"webp"),i=v(r,s,"avif"),l=t==="webp",c=t==="avif";if(n&&(l||a)&&(c||i))return{hash:r,originalExt:t,originalPath:S(r,s,t),processedPaths:[!l&&a?S(r,s,"webp"):null,!c&&i?S(r,s,"avif"):null].filter(Boolean)};let f=await Me(o,t),h=l?null:await de(o),P=c?null:await ue(o),p=C(r,s,t,f),E=!l&&h?C(r,s,"webp",h):null,L=!c&&P?C(r,s,"avif",P):null;return{hash:r,originalExt:t,originalPath:p,processedPaths:[E,L].filter(ee=>!ee?.endsWith(".scdn"))}}function ze(e){if(K.extname(e).toLowerCase().replace(".","")==="svg"){let r=ge.readFileSync(e,"utf-8"),i=new Ot({ignoreAttributes:!1}).parse(r)?.svg;if(!i)return null;if(i["@_width"]&&i["@_height"])return{width:parseFloat(i["@_width"]),height:parseFloat(i["@_height"])};if(i["@_viewBox"]){let[,,l,c]=i["@_viewBox"].split(/\s+/).map(Number);if(l&&c)return{width:l,height:c}}return null}let t=ge.readFileSync(e),s=It(t);return!s.width||!s.height?null:{width:s.width,height:s.height}}function Bt(e,o,t,s,r=""){return t?`https://${t}.smoothcdn.com${r?`/${r}`:""}${s}`:`https://cdn.smoothcdn.com/${e}/${o}${r?`/${r}`:""}${s}`}var We=new _t("get-snippet").description("Output snippet for asset").action(async()=>{let e=x();if(!e){d("No .scdn.json found.");return}let o=await M(e.sources,e.excludes);if(o.length<=0){d("No assets found");return}m(`Found assets ${o.length}`);let t=await Ve({message:"What asset to get snippet for:",choices:o.map(c=>({name:c,value:c}))}),[,...s]=t.split("/"),r=`/${s.join("/")}`,n=t.split(".").pop()?.toLowerCase()??"",a=Bt(e.userSlug,e.projectSlug,e.customSubdomain||"",r,e.version||""),i={extension:n,url:a,assetName:t};if(n==="svg"||T.includes(n)){let c=await ze(t);i.alt=await D({message:"Alt attribute",validate:f=>f?!0:"Alt attribute is required",default:t}),i.critical=await B({message:"Is critical asset (must be loaded above the fold e.g. in hero section)"}),i.width=await D({message:"Width",default:c?.width?.toString()||""}),i.height=await D({message:"Height",default:c?.height?.toString()||""})}(n==="js"||n==="mjs")&&(i.type=await Ve({message:"Script type",choices:[{name:"Standard",value:"standard"},{name:"Critical",value:"critical"},{name:"Asynchronous",value:"async"}]})),n==="css"&&(i.preload=await B({message:"Preload"})),j.includes(n)&&(i.controls=await B({message:"Controls attribute (shows audio control buttons)"}),i.loop=await B({message:"Loop attribute (plays audio in loop)"})),_.includes(n)&&(i.fontFamily=await D({message:"Font family",default:t})),n==="pdf"&&(i.lazy=await B({message:"Lazy load"}),i.title=await D({message:"Title",default:t}),i.width=await D({message:"Width",default:"100%"}),i.height=await D({message:"Height",default:"600"})),Be.includes(n)&&(i.newTab=await B({message:"Open in new tab"}),i.noreferrer=await B({message:'Hide referrer (adds "noreferrer" to rel attribute)'}),i.download=await B({message:"Download attribute"}));let l=ke(i);await Tt.write(l),m(""),m(l),m(""),N("Snippet was copied to clipboard")});import{Command as Mt}from"commander";import{checkbox as Dt,input as He}from"@inquirer/prompts";import kt from"micromatch";function Z(e){if(!e)return!1;let o=e.trim();return o.length<6||o.length>254||o.includes("..")?!1:/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(o)}function Q(e=0,o,t){let{maxTextAssetSize:s,maxImageAssetSize:r}=fe[e],n=o.split(".").pop()?.toLowerCase()??"",a=Te.includes(n),i=_.includes(n),l=T.includes(n),c=j.includes(n),f=q.includes(n);return!a&&!i&&!l&&!c&&!f?`Unsupported file type: ${n}`:(a||i)&&t>s?`Asset too large. Max allowed ${Math.round(s/1024)} KB, trying to send ${Math.round(t/1024)} KB`:(l||f)&&t>r?`Asset too large. Max allowed ${Math.round(r/(1024*1024))} MB, trying to send ${(t/1024/1024).toFixed(2)} MB`:!0}function Re(e=0,o,t){let{maxAudioAssetSize:s}=fe[e],r=o.split(".").pop()?.toLowerCase()??"";return j.includes(r)&&t>s?`Asset too large. Max allowed ${Math.round(s/(1024*1024))} MB, received ${(t/1024/1024).toFixed(2)} MB`:!0}function he(e){try{kt.matcher(e)}catch{return"Invalid pattern"}return e.includes("\0")||e.includes("..")||e.includes("~")||e.startsWith("/")||/^[A-Za-z]:\\/.test(e)?"Contains invalid segments":!0}var Xe=new Mt("grant-access").description("Grant access for smooth resources").option("--force","Override expiration date if access already exists").action(async({force:e=!1})=>{let o=await y(),t=x();if(!t){d("No .scdn.json found.");return}let r=((await o.get(`/projects/${t.projectId}/assets`)).data??[]).filter(n=>n.protected).map(n=>`${n.path}${n.fileName}`);if(r.length===0)d("No protected assets found");else{let n=await Dt({message:"Select protected assets to grant access to:",choices:r.map(c=>({name:c,value:c})),validate:c=>c.length>0?!0:"Select at least one asset."}),a=await He({message:"Enter user email to grant access (mail@example.com):",validate:c=>Z(c)?!0:"Invalid mail format"}),i=await He({message:"Enter expiration date (leave empty if no expiration should be set):"}),l=w("Granting access...");try{let c={force:e,assets:n,email:a,expiresAt:i},f=await o.post(`/projects/${t.projectId}/accesses/grant`,c);f.status===201?g(`Access granted for "${a}"`,l):f.status===200?g(`Access already exists for "${a}"`,l):u("Unexpected response from server",l,f)}catch(c){u("Failed to grant access",l,c)}}});import{Command as Ss}from"commander";import{input as X,confirm as k}from"@inquirer/prompts";import{Command as ws}from"commander";import ys from"form-data";import Y from"fs";import st from"path";import zt from"fs";import Vt from"crypto";import xe from"path";import{execFileSync as Ue}from"child_process";function Wt(e){return Vt.createHash("sha256").update(e).digest("hex")}function Rt(){try{return Ue("ffmpeg",["-version"],{stdio:"ignore"}),!0}catch{return!1}}function Ht(e,o){Ue("ffmpeg",["-y","-i",e,"-map_metadata","-1","-vn","-c:a","aac","-q:a","2","-movflags","+faststart",o],{stdio:"ignore"})}async function Je(e){if(!Rt())return!1;let o=zt.readFileSync(e),t=xe.extname(e).replace(".","").toLowerCase(),s=xe.basename(e,xe.extname(e));if(!j.includes(t))throw new Error(`Unsupported audio extension: .${t}`);let r=Wt(o);A(r);let n=v(r,s,t),a=v(r,s,"m4a"),i=n?S(r,s,t):C(r,s,t,o);if(a)return{hash:r,originalExt:t,originalPath:i,processedPaths:[S(r,s,"m4a")]};let l=S(r,s,"m4a");return Ht(i,l),{hash:r,originalExt:t,originalPath:i,processedPaths:[l]}}import Xt from"fs";import Ut from"crypto";import we from"path";import Jt from"postcss";import qt from"cssnano";function Gt(e){return Ut.createHash("sha256").update(e).digest("hex")}function Kt(e){let o=e.split(`
59
+ `),t=o.reduce((n,a)=>n+a.length,0)/o.length,s=(e.match(/\s/g)?.length??0)/e.length,r=/\/\*/.test(e);return t>200&&s<.12&&!r}async function Zt(e){return(await Jt([qt({preset:["default",{discardComments:!0,normalizeWhitespace:!0,mergeRules:!1,mergeLonghand:!1,reduceIdents:!1,zindex:!1,calc:!1,colormin:!1,normalizeUrls:!1,normalizeTimingFunctions:!1,normalizeUnicode:!1,minifyFontValues:!1,minifySelectors:!1}]})]).process(e,{from:void 0})).css}async function qe(e){let o=Xt.readFileSync(e),t=we.extname(e).replace(".","").toLowerCase(),s=we.basename(e,we.extname(e)),r=Gt(o);if(A(r),v(r,s,t))return{hash:r,originalExt:t,originalPath:S(r,s,t)};let a=o.toString("utf8"),i=o;if(!Kt(a)){let f=await Zt(a);i=Buffer.from(f)}let c=C(r,s,t,i);return{hash:r,originalExt:t,originalPath:c}}import Yt from"fs";import es from"crypto";import ye from"path";import Qt from"ttf2woff2";async function Ge(e,o){return e}async function Ke(e){return Buffer.from(Qt(e))}function ts(e){return es.createHash("sha256").update(e).digest("hex")}async function Ze(e){let o=Yt.readFileSync(e),t=ye.extname(e).replace(".","").toLowerCase(),s=ye.basename(e,ye.extname(e)),r=ts(o);A(r);let n=v(r,s,t),a=v(r,s,"woff2"),i=t==="woff2";if(n&&(i||a))return{hash:r,originalExt:t,originalPath:S(r,s,t),processedPaths:[!i&&a?S(r,s,"woff2"):null].filter(Boolean)};let l=await Ge(o,t),c=i?null:await Ke(o),f=C(r,s,t,l),h=!i&&c?C(r,s,"woff2",c):null;return{hash:r,originalExt:t,originalPath:f,processedPaths:[h].filter(P=>P&&!P.endsWith(".scdn"))}}import Qe from"fs";import ss from"crypto";import Se from"path";import{minify as os}from"terser";function rs(e){return ss.createHash("sha256").update(e).digest("hex")}async function ns(e){return(await os(e,{compress:!1,mangle:{toplevel:!1},format:{comments:!1,semicolons:!0}})).code}function is(e){let o=e.split(`
60
+ `),t=o.reduce((r,n)=>r+n.length,0)/o.length,s=(e.match(/\s/g)?.length??0)/e.length;return t>200&&s<.15&&!/\/\*|\n\s*\/\//.test(e)}async function Ye(e){let o=Qe.readFileSync(e),t=Se.extname(e).replace(".","").toLowerCase(),s=Se.basename(e,Se.extname(e)),r=rs(o);if(A(r),v(r,s,t))return{hash:r,originalExt:t,originalPath:S(r,s,t)};let a=Qe.readFileSync(e),i=a.toString("utf8"),l=a;if(!is(i)){let h=await ns(i);l=Buffer.from(h)}let f=C(r,s,t,l);return{hash:r,originalExt:t,originalPath:f}}import as from"fs";import cs from"crypto";import ve from"path";function ls(e){return cs.createHash("sha256").update(e).digest("hex")}function fs(e){let o=(e.match(/\s/g)?.length??0)/e.length,t=e.split(`
61
+ `).length;return o<.08&&t<=2}function ps(e){let o=JSON.parse(e);return JSON.stringify(o)}async function et(e){let o=as.readFileSync(e),t=ve.extname(e).replace(".","").toLowerCase(),s=ve.basename(e,ve.extname(e)),r=ls(o);if(A(r),v(r,s,t))return{hash:r,originalExt:t,originalPath:S(r,s,t)};let a=o.toString("utf8"),i=o;if(!fs(a)){let f=ps(a);i=Buffer.from(f)}if(!i||i.length===0)throw new Error("JSON minification produced empty output");let c=C(r,s,t,i);return{hash:r,originalExt:t,originalPath:c}}import ms from"fs";import ds from"crypto";import Ee from"path";import{optimize as us}from"svgo";function gs(e){return ds.createHash("sha256").update(e).digest("hex")}function hs(e){let o=(e.match(/\s/g)?.length??0)/e.length,t=/<!--/.test(e),s=e.split(`
62
+ `).length;return o<.1&&s<=2&&!t}function xs(e){let o=console.warn,t=console.info;console.warn=()=>{},console.info=()=>{};let s;try{s=us(e,{multipass:!0,plugins:[{name:"preset-default",params:{overrides:{convertPathData:!1,convertStyleToAttrs:!1,cleanupIds:!1,removeViewBox:!1,inlineStyles:!1}}},"removeUselessStrokeAndFill"]})}finally{console.warn=o,console.info=t}if(!("data"in s)||!s.data)throw new Error("SVG optimization failed");return s.data}async function tt(e){let o=ms.readFileSync(e),s=Ee.parse(e).ext.replace(".","").toLowerCase(),r=Ee.basename(e,Ee.extname(e)),n=gs(o);if(A(n),v(n,r,s))return{hash:n,originalExt:s,originalPath:S(n,r,s)};let i=o.toString("utf8"),l=o;if(!hs(i)){let h=xs(i);l=Buffer.from(h)}let f=C(n,r,s,l);return{hash:n,originalExt:s,originalPath:f}}var Ce=async({force:e=!1,sync:o=!1})=>{let t=await y(),s=x();if(!s){d("No .scdn.json found.");return}let r=!1;if(!s.projectId)d('Missing projectId in config file. Please run "scdn init" or "scdn load" command first.');else try{let n=await t.get("/status"),{plan:a,slug:i}=n.data;s.plan!==a&&(s.plan=a,b(s)),s.userSlug!==i&&(s.userSlug=i,b(s)),m(`Deploying assets${s.version?` for version ${s.version}`:""}...`);let l=await M(s.sources,s.excludes),c=await M(s.protected),f=[];if(l.length>0){let h=w("Deploying asset"),P=0;for(let p of l)if(++P,r&&!e)u(`Selected version was already published "${p}"`,h);else try{let E=st.basename(p),ee=p.replace(E,"").replace(/^\/+|\/+$/g,""),[,...ft]=ee.split("/"),$e=ft.join("/"),U=0;try{U=Y.statSync(p).size}catch{throw new Error(`Cannot read file: ${p}`)}let be=Q(s.plan||0,E,U);if(be!==!0)throw new Error(be);let I=E.split(".").pop()?.toLowerCase()??"",$;if(T.includes(I)&&I!=="avif")$=await De(p);else if(I==="js"||I==="mjs")$=await Ye(p);else if(I==="css")$=await qe(p);else if(I==="json")$=await et(p);else if(I==="svg")$=await tt(p);else if(_.includes(I))$=await Ze(p);else if(j.includes(I)){if($=await Je(p),$===!1)throw new Error("To optimize audio - ffmpeg is required. Install it from https://ffmpeg.org/");if($?.originalPath){try{U=Y.statSync($.originalPath).size}catch{throw new Error(`Cannot read file: ${$.originalPath}`)}let W=Re(s.plan||0,st.basename($.originalPath),U);if(W!==!0)throw new Error(W)}else throw new Error("Audio was not optimized")}else q.includes(I)&&($={originalPath:p,processedPaths:[]});let O=new ys;O.append("asset",Y.createReadStream($?.originalPath?$.originalPath:p)),$?.processedPaths?.forEach(W=>{O.append("sub_assets[]",Y.createReadStream(W))}),O.append("path",$e),O.append("version",s.version||""),O.append("optimize",0),O.append("failIfExist",0),O.append("protected",c.includes(p)?1:0),e&&O.append("force",1),f.push({fileName:E,path:$e});let V=await t.post(`/projects/${s.projectId}/assets`,O,{headers:O.getHeaders()});V.status===201?g(`Deployed "${p}"`,h):V.status===200&&(V.data?.error==="Cannot deploy/override assets on published version"?(r=!0,u(`Failed to deploy ${p}`,h,V)):V.data?.dedupe&&g(`Asset already exists "${p}"`,h))}catch(E){u(`Failed to deploy ${p}`,h,E)}if(o){let p=w("Sync...");try{let E=await t.post(`/projects/${s.projectId}/assets/sync`,{force:e,version:s.version,assetsToSync:f});g(`Sync: ${E?.data?.removed??0} files removed`,p)}catch(E){u(E,p)}}}else d("No assets to deploy")}catch(n){d("Cannot proceed with pushing assets",n)}m("")},ot=new ws("push").option("--force","Override assets on published versions too").option("--sync","Additionally removes files that do not exists in project anymore").description("Push assets to CDN").action(Ce);var rt=new Ss("init").description("Initialize new project").action(async()=>{let e=await y(),o=!1;if(J())m("Detected .scdn.json config file");else{let t=await X({message:"Project name:"});o=await k({message:"Enable versioning:",default:!1});let s=o?await X({message:"Initial version:",default:"1.0.0"}):"",r=await k({message:"Block bots for this variant?",default:!1}),n=await k({message:"Block headless browsers?",default:!1}),a=[],i=!0;for(;i;){let p=await X({message:"Add source path/pattern (glob allowed):",validate:L=>L.trim().length>0||"Source required"});a.push(p.trim()),i=await k({message:"Add another source?",default:!1})}let l=[];if(await k({message:"Add exclude patterns?",default:!1})){let p=!0;for(;p;){let E=await X({message:"Exclude path/pattern:",validate:L=>L.trim().length>0||"Exclude required"});l.push(E.trim()),p=await k({message:"Add another exclude?",default:!1})}}let f=[];if(await k({message:"Add protected patterns?",default:!1})){let p=!0;for(;p;){let E=await X({message:"Protected path/pattern:",validate:L=>L.trim().length>0||"Protected required"});f.push(E.trim()),p=await k({message:"Add another protected?",default:!1})}}let P={project:t,projectSlug:je(t),version:s,blockBots:r,blockHeadless:n,sources:a,excludes:l,protected:f};b(P),m("Created .scdn.json config file")}if(J()){m("Sending to Smooth CDN...");let t=x(),s,r=w(`Creating project "${t.project}"`);try{s=await e.post("/projects",{name:t.project,slug:t.projectSlug||"",withVersioning:o||!!t?.version,version:o||t?.version?t.version:"",block_bots:t.blockBots,block_headless:t.blockHeadless,sources:t?.sources||[],excludes:t?.excludes||[],protected:t?.protected||[],failIfExist:!1}),s.status===201?g(`Created new project "${t.project} ${t.version}"`,r):s.status===200&&g(`Project exist "${t.project} ${t.version}"`,r),s.data.id&&s.data.id!==t.projectId&&(t.projectId=s.data.id,b(t)),await Ce({force:!1}),m("Sent to Smooth CDN")}catch(n){u("Cannot create project",r,n)}}});import{Command as vs}from"commander";import Es from"fs";import Cs from"path";var nt=new vs("inspect-assets").description("Validates assets paths and lists assets for deployments").action(async()=>{let e=x();if(!e){d("No .scdn.json found.");return}m("Checking paths"),e?.sources?.forEach(t=>{let s=he(t);s?N(t):d(`${t} [${s}]`)}),e?.excludes?.forEach(t=>{let s=he(t);s?N(t):d(`${t} [${s}]`)}),m("Checking assets:");let o=await M(e.sources,e.excludes);o.length===0?d("No assets found"):o.forEach(t=>{let s=Cs.basename(t),r=0;try{r=Es.statSync(t).size}catch{throw new Error(`Cannot read file: ${t}`)}let n=Q(e.plan||0,s,r);n===!0?N(s):d(`${s} [${n}]`)}),m("")});import{Command as $s}from"commander";import{select as bs}from"@inquirer/prompts";var it=new $s("load").description("Initialize project that already exists").action(async()=>{let e=x();if(e?.project&&e?.projectSlug)N("Project already initiated in .scdn config file.");else{let o=w("Fetching available projects...");try{let s=await(await y()).get("/projects?full=1");if(s.data.length>0){g(`${s.data.length} projects available`,o);let r=await bs({message:"Which project to load:",choices:s.data.map(a=>({name:a.name,value:a.id}))}),n=s.data.find(a=>a.id===r);b({...e,project:n.name,projectId:n.id,projectSlug:n.slug,customSubdomain:n?.customSubdomain||"",version:n.withVersioning?n.latestVersion||n?.versions[0]?.version||"1.0.0":"",blockBots:!!n.blockBots,blockHeadless:!!n.blockHeadless,sources:n?.sources?JSON.parse(n.sources):[],excludes:n?.excludes?JSON.parse(n.excludes):[],protected:n?.protected?JSON.parse(n.protected):[]}),N("Config file saved")}else u("No projects available to be loaded from Smooth CDN",o)}catch(t){u("Failed to fetch projects",o,t)}}});import{Command as As}from"commander";var at=new As("publish-version").description("Publish selected version").argument("[version]","Version number, e.g. 1.0.0").action(async(e="")=>{let o=await y(),t=x();if(!t){d("No .scdn.json found.");return}let s=e||t.version;if(s){let r=w(`Publishing version "${s}"`);try{let n=await o.post(`/projects/${t.projectId}/versions/publish`,{version:s});n.status===201?g(`Published new version "${s}"`,r):n.status===200&&g(`Version already published "${s}"`,r)}catch(n){u(`Cannot publish version ${s}`,r,n)}}else d('Missing version. Please run "scdn create-version <version>" first.')});import{Command as Ps}from"commander";import{input as Fs,select as Ns}from"@inquirer/prompts";var ct=new Ps("revoke-access").description("Revoke access for smooth resources").action(async()=>{let e=await y(),o=x();if(!o){d("No .scdn.json found.");return}let t=await Fs({message:"Enter user email to revoke access (mail@example.com):",validate:s=>Z(s)?!0:"Invalid mail format"});try{let s=w("Revoking access..."),r=await e.post("/customer/accesses",{email:t});r.data?.length<=0&&u(`No accesses found for "${t}"`,s),g(`Fetched ${r.data.length} accesses`,s);let n=await Ns({message:"What access to revoke:",choices:r.data.map(l=>({name:`${l.project} (${l.assets.join(",")})`,value:l.id}))}),a=w("Revoking access..."),i=await e.post(`/projects/${o.projectId}/accesses/${n}/revoke`);i.status===201?g("Selected access revoked",a):i.status===200?g("Selected access already revoked",a):u("Failed to revoke access",a)}catch(s){d("Failed to revoke access",s)}});import{Command as js}from"commander";var Is=["FREE","PRO","PREMIUM"],lt=new js("status").description("Get a status summary").action(async()=>{let e=await y(),o=await x();if(!o){d("No .scdn.json found.");return}let t,s=w("Fetching status...");try{t=await e.get("/status"),g("Fetched",s);try{let{name:r,email:n,plan:a,slug:i,planExpiration:l,limits:c,usage:f,projects:h=[]}=t.data;o.plan!==a&&(o.plan=a,b(o)),o.userSlug!==i&&(o.userSlug=i,b(o)),m(`Logged in as ${r} (${i} - ${n})`),m(`Plan: ${Is[a]} ${l?`(Expires at ${ae(l)})`:""}`),f&&(m("Usage limits:"),m(` Requests: ${R(f.requests)}/${R(f.maxRequests)}`),m(` Bandwidth: ${ce(f.bandwidth)}/${ce(f.maxBandwidth)}`),f.periodEnd&&m(` Resets at: ${ae(f.periodEnd)}`)),m(""),m(`Projects (used projects: ${h.length}/${c.projects}):`),h.map((P,p)=>{m(` ${p+1}. ${P.name} (used assets: ${R(P.assetsCount)}/${R(c.assetsPerProject)})`)})}catch(r){u("Failed to parse status",s,r)}}catch(r){u("Failed to parse status",s,r)}});import{createRequire as Ls}from"module";var _s=Ls(import.meta.url),Ts=_s("../package.json"),F=new Os;F.name("scdn").description("Smooth CDN CLI").version(Ts.version);F.addCommand(Ie);F.addCommand(We);F.addCommand(Xe);F.addCommand(rt);F.addCommand(nt);F.addCommand(it);F.addCommand(Oe);F.addCommand(Le);F.addCommand(at);F.addCommand(ot);F.addCommand(ct);F.addCommand(lt);F.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smoothcdn/cli",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "private": false,