devbox-sdk
Version:
A lightweight development environment management tool based on Kubernetes
2 lines • 7.83 kB
JavaScript
import {customAlphabet}from'nanoid';import*as y from'@kubernetes/client-node';import {PassThrough}from'stream';var x=class{constructor(e,o,t,r){this.k8sExec=e,this.namespace=o,this.podName=t,this.containerName=r;}async execCommand(e,o=null,t=null,r=3){let s=n=>new Promise(l=>setTimeout(l,n));for(let n=1;n<=r;n++)try{return await this.executeWithTimeout(this.namespace,this.podName,this.containerName,e,o,t)}catch(l){if(!this.isRetryableError(l)||n===r)throw new Error(`Command execution failed after ${n} attempts: ${l.message}`);await s(Math.min(1e3*Math.pow(2,n-1),5e3));}throw new Error("Unexpected execution path")}isRetryableError(e){let o=["ECONNRESET","ETIMEDOUT","ECONNREFUSED","Unexpected server response: 500","WebSocket closed with code"],t=(e==null?void 0:e.message)||(e==null?void 0:e.toString())||"";return o.some(r=>t.includes(r))}executeWithTimeout(e,o,t,r,s,n,l=3e4){return new Promise((p,m)=>{let b=new PassThrough,u=Buffer.alloc(0),v;n?n.on("data",c=>{u=Buffer.concat([u,c]);}):(n=new PassThrough,n.on("data",c=>{u=Buffer.concat([u,c]);}));let g=n,d=()=>{clearTimeout(v),b.removeAllListeners(),g.removeAllListeners(),s==null||s.removeAllListeners(),b.destroy(),n||g.destroy();};this.k8sExec.exec(e,o,t,r,g,b,s,!1).then(c=>{v=setTimeout(()=>{d(),c.terminate(),m(new Error(`Command execution timed out after ${l}ms`));},l),c.on("error",i=>{d(),m(new Error(`WebSocket error: ${(i==null?void 0:i.message)||"Unknown error"}`));}),c.on("close",(i,f)=>{d(),i!==1e3?m(new Error(`WebSocket closed with code ${i}: ${f||"No reason provided"}`)):p(u.toString());}),b.on("data",i=>{let f=i.toString();d(),m(new Error(`Command error: ${f}`));}),g.on("end",()=>{}),g.on("error",i=>{d(),m(i);}),s&&(s.on("error",i=>{d(),m(i);}),s.on("end",()=>{}));}).catch(c=>{d(),m(new Error(`Failed to initialize command: ${c.message}`));});})}async writeFile(e,o){let t=new PassThrough;return t.end(o),await this.execCommand(["sh","-c",`dd of=${e} status=none bs=32767`],t),"File written successfully"}async readFile(e){try{return await this.execCommand(["cat",e])}catch(o){throw new Error(`Failed to read file: ${o}`)}}async mkdir(e){return await this.execCommand(["mkdir","-p",e])}async rm(e){return await this.execCommand(["rm","-rf",e])}async mv(e,o){return await this.execCommand(["mv",e,o])}};var h=customAlphabet("abcdefghijklmnopqrstuvwxyz"),a=class a{static getApiUrlFromKubeconfig(e){let o=new y.KubeConfig;o.loadFromString(e);let t=o.getCurrentCluster();if(!t)throw new Error("No cluster found in kubeconfig");let r=t.server;return `https://devbox.${new URL(r).hostname}`}static getDomainSuffixFromKubeconfig(e){let o=new y.KubeConfig;o.loadFromString(e);let t=o.getCurrentCluster();if(!t)throw new Error("No cluster found in kubeconfig");let r=t.server;return `sealos${new URL(r).hostname.split(".")[0]}.site`}constructor(e){this.kubeconfig=e.kubeconfig,this.id=e.id,this.fileSystem=e.fileSystem,this.apiUrl=a.getApiUrlFromKubeconfig(e.kubeconfig),this.domainSuffix=a.getDomainSuffixFromKubeconfig(e.kubeconfig);}static async create(e){var p,m;let o=this.getDomainSuffixFromKubeconfig(e.kubeconfig),t=`devbox-sdk-${h(12)}`,r=h(12),s=`devbox-${h(12)}`,n=`${h(12)}.${o}`,l={devboxForm:{name:t,runtimeType:e.runtime.split("-")[0],runtimeVersion:e.runtime,cpu:this.DEFAULT_CPU,memory:this.DEFAULT_MEMORY,networks:[{networkName:s,portName:r,port:this.DEFAULT_PORT,protocol:"HTTP",openPublicDomain:!0,publicDomain:n,customDomain:""}]},runtimeNamespaceMap:this.RUNTIME_NAMESPACE_MAP};try{let b=this.getApiUrlFromKubeconfig(e.kubeconfig),u=await fetch(`${b}/api/createDevbox`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`${encodeURIComponent(e.kubeconfig)}`},body:JSON.stringify(l)});if(!u.ok)throw new Error(`HTTP error! status: ${u.status}`);let v=await u.json();if(v.error)throw new Error(v.error);let g=await this.getDetail(t,e.kubeconfig);if(!((m=(p=g.status.commitHistory)==null?void 0:p[0])!=null&&m.pod))throw new Error("Pod name not found in commit history");let d=new y.KubeConfig;d.loadFromString(e.kubeconfig);let c=new x(new y.Exec(d),g.metadata.namespace,g.status.commitHistory[0].pod,t);return new a({kubeconfig:e.kubeconfig,id:t,fileSystem:c})}catch(b){throw new Error(`Failed to create DevBox: ${b.message}`)}}static async getDetail(e,o){try{let t=this.getApiUrlFromKubeconfig(o),r=await fetch(`${t}/api/getDevboxByName?devboxName=${e}`,{headers:{Authorization:`${encodeURIComponent(o)}`}});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);let s=await r.json();if(s.error)throw new Error(s.error);return s.data}catch(t){throw new Error(`Failed to get DevBox details: ${t.message}`)}}static async delete(e,o){try{let t=this.getApiUrlFromKubeconfig(o),r=await fetch(`${t}/api/delDevbox?devboxName=${e}`,{method:"DELETE",headers:{Authorization:`${encodeURIComponent(o)}`}});if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);let s=await r.json();if(s.error)throw new Error(s.error)}catch(t){throw new Error(`Failed to delete DevBox: ${t.message}`)}}async getDetail(){return a.getDetail(this.id,this.kubeconfig)}async delete(){return a.delete(this.id,this.kubeconfig)}static async list(e){try{let o=this.getApiUrlFromKubeconfig(e),t=await fetch(`${o}/api/getDevboxList`,{headers:{Authorization:`${encodeURIComponent(e)}`}});if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);let r=await t.json();if(r.error)throw new Error(r.error);return r.data}catch(o){throw new Error(`Failed to list DevBoxes: ${o.message}`)}}static async get(e,o){let t=await this.getDetail(e,o),r=new y.KubeConfig;r.loadFromString(o);let s=new x(new y.Exec(r),t.metadata.namespace,t.status.commitHistory[0].pod,e);return new a({kubeconfig:o,id:e,fileSystem:s})}};a.DEFAULT_CPU=1e3,a.DEFAULT_MEMORY=2048,a.DEFAULT_PORT=3e3,a.RUNTIME_NAMESPACE_MAP={"c-gcc-12-2-0-2024-11-12-0651":"devbox-system","cpp-gcc-12-2-0-2024-11-12-0651":"devbox-system","go-1-22-5-2024-11-12-0651":"devbox-system","go-1-23-0-2024-11-12-0651":"devbox-system","java-openjdk17-2024-11-12-0651":"devbox-system","net-8-0-2024-11-12-0651":"devbox-system","node.js-22-2024-11-13-0700":"devbox-system","node.js-18-2024-11-13-0700":"devbox-system","node.js-20-2024-11-13-0700":"devbox-system","php-8-2-20-2024-11-13-0347":"devbox-system","php-7-4-2024-11-13-0347":"devbox-system","python-3-10-2024-11-12-0651":"devbox-system","python-3-11-2024-11-12-0651":"devbox-system","python-3-12-2024-11-12-0651":"devbox-system","rust-1-81-0-2024-11-12-0651":"devbox-system","angular-v18-2024-11-13-0835":"devbox-system","astro-4-10-0-2024-11-13-0835":"devbox-system","chi-v5-1-0-2024-11-13-0740":"devbox-system","django-4-2-16-2024-11-13-0740":"devbox-system","docusaurus-3-5-2-2024-11-13-0835":"devbox-system","echo-v4-12-0-2024-11-13-0740":"devbox-system","express.js-4-21-0-2024-11-13-0835":"devbox-system","flask-3-0-3-2024-11-13-0740":"devbox-system","gin-v1-10-0-2024-11-13-0740":"devbox-system","hexo-7-3-0-2024-11-13-0835":"devbox-system","hugo-v0-135-0-2024-11-13-0740":"devbox-system","iris-v12-2-11-2024-11-13-0740":"devbox-system","next.js-14-2-5-2024-11-13-0835":"devbox-system","nginx-1-22-1-2024-11-13-0835":"devbox-system","nuxt3-v3-13-2024-11-13-0835":"devbox-system","quarkus-3-16-1-2024-11-13-0740":"devbox-system","quarkus-docker-2024-11-01-0724":"devbox-system","react-18-2-0-2024-11-13-0835":"devbox-system","rocket-0-5-1-2024-11-13-0740":"devbox-system","sealaf-1-0-0-2024-11-13-0835":"devbox-system","spring-boot-3-3-2-2024-11-13-0740":"devbox-system","svelte-6-4-0-2024-11-13-0835":"devbox-system","umi-4-3-27-2024-11-13-0835":"devbox-system","vert.x-4-5-10-2024-11-13-0740":"devbox-system","vitepress-1-4-0-2024-11-13-0835":"devbox-system","vue-v3-4-29-2024-11-13-0835":"devbox-system","debian-ssh-12-6-2024-11-11-0803":"devbox-system","ubuntu-24-04-2024-11-01-1417":"devbox-system"};var E=a;
export{E as DevBox};