phala 1.0.13 → 1.0.15
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.js +6 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
@@ -55,9 +55,9 @@ services:
|
|
55
55
|
volumes:
|
56
56
|
- postgres-data:/var/lib/postgresql/data:rw
|
57
57
|
ports:
|
58
|
-
-
|
58
|
+
- '127.0.0.1:5432:5432'
|
59
59
|
healthcheck:
|
60
|
-
test: [
|
60
|
+
test: ['CMD-SHELL', 'pg_isready -U $\${POSTGRES_USER} -d $\${POSTGRES_DB}']
|
61
61
|
interval: 5s
|
62
62
|
timeout: 5s
|
63
63
|
retries: 5
|
@@ -73,7 +73,8 @@ services:
|
|
73
73
|
{{#each envVars}} - {{{this}}}
|
74
74
|
{{/each}}
|
75
75
|
ports:
|
76
|
-
-
|
76
|
+
- '3000:3000'
|
77
|
+
- '50000-50100:50000-50100/udp'
|
77
78
|
depends_on:
|
78
79
|
postgres:
|
79
80
|
condition: service_healthy
|
@@ -98,7 +99,7 @@ services:
|
|
98
99
|
{{#each envVars}} - {{{this}}}
|
99
100
|
{{/each}}
|
100
101
|
restart: always
|
101
|
-
`;function Oe(t){try{return JSON.stringify(t)}catch(e){return e instanceof Error&&e.message.includes("cyclic")?"[Cyclic Object]":String(t)}}var Ue=class{client;apiKey=null;constructor(e){r.debug(`Creating API client with base URL: ${e}`),this.client=Sr.create({baseURL:e,headers:{"Content-Type":"application/json","User-Agent":`tee-cloud-cli/${rt}`}}),this.client.interceptors.request.use(async o=>{if(!this.apiKey){if(this.apiKey=await Z(),!this.apiKey)throw new Error('API key not found. Please set an API key first with "phala auth login"');r.debug(`API key loaded: ${this.apiKey.substring(0,5)}...`)}return o.headers["X-API-Key"]=this.apiKey,r.debug(`Making request to: ${o.baseURL}${o.url}`),o}),this.client.interceptors.response.use(o=>(r.debug(`Received successful response from: ${o.config.url}`),o),o=>{if(o.response){let{status:n,data:s}=o.response;r.debug(`Received error response: ${n} - ${Oe(s)}`),n===401?r.error("Authentication failed. Please check your API key."):n===403?r.error("You do not have permission to perform this action."):n===404?r.error("Resource not found."):r.error(`API Error (${n}): ${s.message||Oe(s)}`)}else o.request?(r.error("No response received from the server. Please check your internet connection."),r.debug(`Request details: ${Oe(o.request).substring(0,200)}...`)):r.error(`Error: ${o.message}`);return Promise.reject(o)})}async get(e,o){try{return r.debug(`GET request to: ${e}`),(await this.client.get(e,o)).data}catch(n){throw r.debug(`GET request failed: ${n instanceof Error?n.message:String(n)}`),n}}async post(e,o,n){try{return r.debug(`POST request to: ${e}`),(await this.client.post(e,o,n)).data}catch(s){throw r.debug(`POST request failed: ${s instanceof Error?s.message:String(s)}`),s}}async put(e,o,n){try{return r.debug(`PUT request to: ${e}`),(await this.client.put(e,o,n)).data}catch(s){throw r.debug(`PUT request failed: ${s instanceof Error?s.message:String(s)}`),s}}async delete(e,o){try{return r.debug(`DELETE request to: ${e}`),(await this.client.delete(e,o)).data}catch(n){throw r.debug(`DELETE request failed: ${n instanceof Error?n.message:String(n)}`),n}}async patch(e,o,n){try{return r.debug(`PATCH request to: ${e}`),(await this.client.patch(e,o,n)).data}catch(s){throw r.debug(`PATCH request failed: ${s instanceof Error?s.message:String(s)}`),s}}};r.debug(`Initializing API client with URL: ${Me}`);var $=new Ue(Me);import{z as i}from"zod";import{INVALID as wr,ParseStatus as Er,ZodIssueCode as J,ZodParsedType as it,ZodType as xr,addIssueToContext as Q,z as at}from"zod";var Tr="ZodDecimal",$r=/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/,ce=class extends xr{_parse(e){if(e.data!==null&&typeof e.data=="object"&&"toNumber"in e.data&&(e.data=e.data.toNumber()),this._def.coerce&&(e.data=Number(e.data)),this._getType(e)!==it.number){let c=this._getOrReturnCtx(e);return Q(c,{code:J.invalid_type,expected:it.number,received:c.parsedType}),wr}let n,s=new Er;for(let c of this._def.checks)if(c.kind==="precision"){let a=e.data.toString().match($r);Math.max((a[1]?a[1].length:0)-(a[2]?parseInt(a[2],10):0),0)>c.value&&(n=this._getOrReturnCtx(e,n),Q(n,{code:J.custom,message:c.message,params:{precision:c.value}}),s.dirty())}else c.kind==="wholeNumber"?e.data.toString().split(".")[0].length>c.value&&(n=this._getOrReturnCtx(e,n),Q(n,{code:J.custom,message:c.message,params:{wholeNumber:c.value}}),s.dirty()):c.kind==="min"?(c.inclusive?e.data<c.value:e.data<=c.value)&&(n=this._getOrReturnCtx(e,n),Q(n,{code:J.too_small,minimum:c.value,type:"number",inclusive:c.inclusive,exact:!1,message:c.message}),s.dirty()):c.kind==="max"?(c.inclusive?e.data>c.value:e.data>=c.value)&&(n=this._getOrReturnCtx(e,n),Q(n,{code:J.too_big,maximum:c.value,type:"number",inclusive:c.inclusive,exact:!1,message:c.message}),s.dirty()):c.kind==="finite"&&(Number.isFinite(e.data)||(n=this._getOrReturnCtx(e,n),Q(n,{code:J.not_finite,message:c.message}),s.dirty()));return{status:s.value,value:e.data}}setLimit(e,o,n,s){return new ce({...this._def,checks:[...this._def.checks,{kind:e,value:o,inclusive:n,message:s}]})}_addCheck(e){return new ce({...this._def,checks:[...this._def.checks,e]})}lte(e,o){return this.setLimit("max",e,!0,o)}lt(e,o){return this.setLimit("max",e,!1,o)}max=this.lte;gt(e,o){return this.setLimit("min",e,!1,o)}gte(e,o){return this.setLimit("min",e,!0,o)}min=this.gte;precision(e,o){return this._addCheck({kind:"precision",value:e,message:o})}wholeNumber(e,o){return this._addCheck({kind:"wholeNumber",value:e,message:o})}get minValue(){let e=null;for(let o of this._def.checks)o.kind==="min"&&(e===null||o.value>e)&&(e=o.value);return e}get maxValue(){let e=null;for(let o of this._def.checks)o.kind==="max"&&(e===null||o.value<e)&&(e=o.value);return e}positive(e){return this._addCheck({kind:"min",value:0,inclusive:!1,message:e})}negative(e){return this._addCheck({kind:"max",value:0,inclusive:!1,message:e})}nonpositive(e){return this._addCheck({kind:"max",value:0,inclusive:!0,message:e})}nonnegative(e){return this._addCheck({kind:"min",value:0,inclusive:!0,message:e})}finite(e){return this._addCheck({kind:"finite",message:e})}safe(e){return this._addCheck({kind:"min",inclusive:!0,value:Number.MIN_SAFE_INTEGER,message:e})._addCheck({kind:"max",inclusive:!0,value:Number.MAX_SAFE_INTEGER,message:e})}get isFinite(){let e=null,o=null;for(let n of this._def.checks){if(n.kind==="finite")return!0;n.kind==="min"?(o===null||n.value>o)&&(o=n.value):n.kind==="max"&&(e===null||n.value<e)&&(e=n.value)}return Number.isFinite(o)&&Number.isFinite(e)}},X=ce;Ye(X,"create",e=>new ce({checks:[],typeName:Tr,coerce:e?.coerce??!1}));var ct=at.object({template:at.string().min(1,"Template cannot be empty")});var Pr=i.object({password:i.string(),registry:i.string().nullable(),username:i.string()}),Dr=i.object({docker_compose_file:i.string(),docker_config:Pr.optional(),features:i.array(i.string()),kms_enabled:i.boolean(),manifest_version:i.number(),name:i.string(),public_logs:i.boolean(),public_sysinfo:i.boolean(),runner:i.string().optional(),salt:i.string().nullable().optional(),tproxy_enabled:i.boolean(),version:i.string().optional()}),Ar=i.object({name:i.string(),image:i.string(),compose_file:Dr,vcpu:i.number(),memory:i.number(),disk_size:i.number(),ports:i.array(i.any())}),Ir=i.object({id:i.string(),name:i.string(),status:i.string(),uptime:i.string(),app_url:i.string(),app_id:i.string(),instance_id:i.string(),configuration:Ar,exited_at:i.string(),boot_progress:i.string(),boot_error:i.string(),shutdown_progress:i.string(),image_version:i.string()}),Rr=i.object({id:i.number(),username:i.string()}),Fr=i.object({id:i.number(),name:i.string()}),ze=i.object({hosted:Ir,name:i.string(),managed_user:Rr,node:Fr,listed:i.boolean(),status:i.string(),in_progress:i.boolean(),dapp_dashboard_url:i.string().nullable(),syslog_endpoint:i.string(),allow_upgrade:i.boolean()}),me=i.object({id:i.number(),name:i.string(),status:i.string(),teepod_id:i.number().nullable(),teepod:i.object({id:i.number(),name:i.string()}).nullable(),user_id:i.number(),app_id:i.string(),vm_uuid:i.string().nullable(),instance_id:i.string().nullable(),app_url:i.string().nullable(),base_image:i.string(),vcpu:i.number(),memory:i.number(),disk_size:i.number(),manifest_version:i.number(),version:i.string(),runner:i.string(),docker_compose_file:i.string(),features:i.array(i.string()).nullable(),created_at:i.string(),encrypted_env_pubkey:i.string()}),mt=i.object({app_env_encrypt_pubkey:i.string(),app_id_salt:i.string()}),lt=i.object({id:i.number(),teepod_id:i.number().nullable(),teepod:i.object({id:i.number(),name:i.string()}).nullable(),name:i.string(),status:i.string(),in_progress:i.boolean(),app_id:i.string(),vm_uuid:i.string(),instance_id:i.string(),vcpu:i.number(),memory:i.number(),disk_size:i.number(),base_image:i.string(),encrypted_env_pubkey:i.string(),listed:i.boolean(),project_id:i.string(),project_type:i.string().nullable()}),pt=i.object({username:i.string(),email:i.string(),credits:X.create({coerce:!0}),granted_credits:X.create({coerce:!0}),role:i.string(),avatar:i.string(),flag_reset_password:i.boolean(),team_name:i.string(),team_tier:i.string(),trial_ended_at:i.string().nullable()}),un=i.array(ze),dt=i.object({detail:i.string()}),fn=i.object({key:i.string(),value:i.string()}),ut=i.object({name:i.string(),description:i.string().optional(),version:i.array(i.number()).optional(),is_dev:i.boolean().optional(),rootfs_hash:i.string().optional(),shared_ro:i.boolean().optional(),cmdline:i.string().optional(),kernel:i.string().optional(),initrd:i.string().optional(),hda:i.string().nullable().optional(),rootfs:i.string().optional(),bios:i.string().optional()}),Mr=i.object({teepod_id:i.number().nullable(),name:i.string(),listed:i.boolean(),resource_score:i.number(),remaining_vcpu:i.number(),remaining_memory:i.number(),remaining_cvm_slots:i.number(),images:i.array(ut).optional()}),Vr=i.object({max_instances:i.number().nullable(),max_vcpu:i.number().nullable(),max_memory:i.number().nullable(),max_disk:i.number().nullable()}),ft=i.object({tier:i.string(),capacity:Vr,nodes:i.array(Mr)}),Lr=i.object({is_online:i.boolean(),is_public:i.boolean(),error:i.string().nullable(),internal_ip:i.string(),latest_handshake:i.string(),public_urls:i.array(i.object({app:i.string(),instance:i.string()}))}),gt=i.object({is_online:i.boolean(),is_public:i.boolean(),error:i.string().nullable(),app_certificates:i.array(i.object({subject:i.object({common_name:i.string().nullable(),organization:i.string().nullable(),country:i.string().nullable(),state:i.string().nullable().optional(),locality:i.string().nullable().optional()}),issuer:i.object({common_name:i.string().nullable(),organization:i.string().nullable(),country:i.string().nullable()}),serial_number:i.string(),not_before:i.string(),not_after:i.string(),version:i.string(),fingerprint:i.string(),signature_algorithm:i.string(),sans:i.string().nullable(),is_ca:i.boolean(),position_in_chain:i.number(),quote:i.string().nullable()})).nullable(),tcb_info:i.object({mrtd:i.string(),rootfs_hash:i.string(),rtmr0:i.string(),rtmr1:i.string(),rtmr2:i.string(),rtmr3:i.string(),event_log:i.array(i.object({imr:i.number(),event_type:i.number(),digest:i.string(),event:i.string(),event_payload:i.string()}))}).nullable(),compose_file:i.string().nullable()});function ht(t){try{return JSON.stringify(t)}catch(e){return e instanceof Error&&e.message.includes("cyclic")?"[Cyclic Object]":String(t)}}async function W(){try{r.debug(`Fetching user info from ${x.USER_INFO}`);let t=await $.get(x.USER_INFO);r.debug(`Received response: ${ht(t)}`);try{return pt.parse(t)}catch(e){throw r.error(`Failed to parse user info response: ${e}`),r.debug(`Response structure: ${ht(t)}`),e}}catch(t){throw r.error(`Failed to get user info: ${t instanceof Error?t.message:String(t)}`),new Error(`Failed to get user info: ${t instanceof Error?t.message:String(t)}`)}}var yt=new Nr().name("login").description("Set the API key for authentication").argument("[api-key]","Phala Cloud API key to set").action(async t=>{try{let e;if(!t)t=(await Or({type:"password",name:"apiKey",message:"Enter your API key:",validate:async n=>{if(n.length===0)return"API key cannot be empty";try{if(await Re(n),e=await W(),!e.username)return await ie(),"Invalid API key"}catch{return"Invalid API key"}return!0}})).apiKey;else if(await Re(t),e=await W(),!e.username)return await ie(),"Invalid API key";r.success(`Welcome ${e.username}! API key validated and saved successfully`),r.break(),r.info(`Open in Web UI at ${w}/dashboard/`)}catch(e){r.error(`Failed to set API key: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}});import{Command as Ur}from"commander";var bt=new Ur().name("logout").description("Remove the stored API key").action(async()=>{try{await ie(),r.success("API key removed successfully")}catch(t){r.error(`Failed to remove API key: ${t instanceof Error?t.message:String(t)}`),process.exit(1)}});import{Command as zr}from"commander";var vt=new zr().name("status").description("Check authentication status").option("-j, --json","Output in JSON format").option("-d, --debug","Enable debug output").action(async t=>{try{t.debug&&(process.env.DEBUG="true");let e=await Z();if(!e){r.warn('Not authenticated. Please set an API key with "phala auth login"');return}r.debug(`Using API key: ${e.substring(0,5)}...`);let o=r.startSpinner("Checking authentication status");try{let n=await W();if(o.stop(!0),t.json){console.log(JSON.stringify(n,null,2));return}r.break(),r.success(`Authenticated as ${n.username}`);let s={Username:n.username,Email:n.email,Role:n.role,Team:`${n.team_name} (${n.team_tier})`,Credits:`$${(n.credits+n.granted_credits).toFixed(2)}`};n.trial_ended_at&&(s["Trial Ended At"]=n.trial_ended_at),r.keyValueTable(s,{borderStyle:"rounded"})}catch(n){o.stop(!1),r.error("Authentication failed. Your API key may be invalid or expired."),r.info('Please set a new API key with "phala auth login"'),t.debug&&r.debug(`Error details: ${n instanceof Error?n.message:String(n)}`)}}catch(e){r.error(`Failed to check authentication status: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}});var Ct=new jr().name("auth").description("Authenticate with Phala Cloud").addCommand(yt).addCommand(bt).addCommand(vt);import{Command as no}from"commander";import{Command as Qr}from"commander";import{execa as Gr}from"execa";import O from"node:fs";import pe from"node:path";import Hr from"handlebars";import{exec as qr,spawn as Yr}from"node:child_process";import{promisify as Zr}from"node:util";import Et from"node:os";import Wr from"inquirer";import je from"node:fs";import We from"node:path";function B(t,e=process.cwd()){let o=We.resolve(e,t);if(!je.existsSync(o))throw new Error(`File not found at ${o}`);return!0}async function K(t,e,o="file",n=process.cwd()){return(await Wr.prompt([{type:"input",name:o,message:t,default:e,validate:c=>{let a=We.resolve(n,c);return je.existsSync(a)?!0:`File not found at ${a}`}}]))[o]}function Ce(t,e){for(let o of t){let n=We.join(process.cwd(),o);if(je.existsSync(n))return e?r.info(e.replace("{path}",n)):r.info(`File detected: ${n}`),o}}import*as R from"node:fs";import*as z from"node:path";import*as ee from"node:os";import{execSync as te,spawn as Br}from"node:child_process";import*as Be from"node:net";var A={version:"0.1.4",baseUrl:"https://github.com/Leechael/tappd-simulator/releases/download/v0.1.4",installDir:z.join(ee.homedir(),".phala-cloud","tappd-simulator"),defaultLogPath:z.join(ee.homedir(),".phala-cloud","logs","tappd-simulator.log"),platforms:{darwin:{filename:"tappd-simulator-0.1.4-aarch64-apple-darwin.tgz",extractedFolder:"tappd-simulator-0.1.4-aarch64-apple-darwin",socketArg:"unix:/tmp/tappd.sock"},linux:{filename:"tappd-simulator-0.1.4-x86_64-linux-musl.tgz",extractedFolder:"tappd-simulator-0.1.4-x86_64-linux-musl",socketArg:"unix:/tmp/tappd.sock"},win32:{filename:"tappd-simulator-0.1.4-x86_64-pc-windows-msvc.tgz",extractedFolder:"tappd-simulator-0.1.4-x86_64-pc-windows-msvc",socketArg:"127.0.0.1:8090"}}};function kt(){try{if(!R.existsSync(A.installDir))return!1;let t=ee.platform();if(!A.platforms[t])throw new Error(`Unsupported platform: ${t}`);let e=z.join(A.installDir,A.platforms[t].extractedFolder);if(!R.existsSync(e))return!1;let n=z.join(e,t==="win32"?"tappd-simulator.exe":"tappd-simulator");return R.existsSync(n)}catch(t){return r.error("Error checking if simulator is installed:",t),!1}}function le(){let t=ee.platform();if(!A.platforms[t])throw new Error(`Unsupported platform: ${t}. Only darwin, linux, and win32 are supported.`);return t}async function _t(t){let e=o=>{r.info(o),t&&t(o)};try{let o=le(),n=A.platforms[o];R.existsSync(A.installDir)||(r.info(`Creating installation directory at ${A.installDir}`),R.mkdirSync(A.installDir,{recursive:!0})),process.chdir(A.installDir);let s=`${A.baseUrl}/${n.filename}`;r.info(`Downloading simulator from ${s}`),te(`wget ${s}`,{stdio:"inherit"}),r.info(`Extracting ${n.filename}`),te(`tar -xvf ${n.filename}`,{stdio:"inherit"}),r.success("Simulator installation completed successfully")}catch(o){throw r.error("Error installing simulator:",o),new Error(`Failed to install simulator: ${o}`)}}async function St(t={}){try{let e=le(),o=A.platforms[e],n=z.join(A.installDir,o.extractedFolder);process.chdir(n);let s=e==="win32"?"tappd-simulator.exe":"./tappd-simulator",c={background:t.background??!0,logToFile:t.logToFile??!0,logFilePath:t.logFilePath??A.defaultLogPath};if(c.logToFile){let p=z.dirname(c.logFilePath);R.existsSync(p)||R.mkdirSync(p,{recursive:!0}),r.info(`Simulator logs will be written to: ${c.logFilePath}`)}r.info(`Starting simulator with: ${s} -l ${o.socketArg}`);let a="inherit",u=null;c.logToFile&&(u=R.createWriteStream(c.logFilePath,{flags:"a"}),a=["ignore",u,u]);let y=Br(s,["-l",o.socketArg],{stdio:a,shell:e==="win32",detached:c.background});if(u){let p=new Date().toISOString();u.write(`
|
102
|
+
`;function Oe(t){try{return JSON.stringify(t)}catch(e){return e instanceof Error&&e.message.includes("cyclic")?"[Cyclic Object]":String(t)}}var Ue=class{client;apiKey=null;constructor(e){r.debug(`Creating API client with base URL: ${e}`),this.client=Sr.create({baseURL:e,headers:{"Content-Type":"application/json","User-Agent":`tee-cloud-cli/${rt}`}}),this.client.interceptors.request.use(async o=>{if(!this.apiKey){if(this.apiKey=await Z(),!this.apiKey)throw new Error('API key not found. Please set an API key first with "phala auth login"');r.debug(`API key loaded: ${this.apiKey.substring(0,5)}...`)}return o.headers["X-API-Key"]=this.apiKey,r.debug(`Making request to: ${o.baseURL}${o.url}`),o}),this.client.interceptors.response.use(o=>(r.debug(`Received successful response from: ${o.config.url}`),o),o=>{if(o.response){let{status:n,data:s}=o.response;r.debug(`Received error response: ${n} - ${Oe(s)}`),n===401?r.error("Authentication failed. Please check your API key."):n===403?r.error("You do not have permission to perform this action."):n===404?r.error("Resource not found."):r.error(`API Error (${n}): ${s.message||Oe(s)}`)}else o.request?(r.error("No response received from the server. Please check your internet connection."),r.debug(`Request details: ${Oe(o.request).substring(0,200)}...`)):r.error(`Error: ${o.message}`);return Promise.reject(o)})}async get(e,o){try{return r.debug(`GET request to: ${e}`),(await this.client.get(e,o)).data}catch(n){throw r.debug(`GET request failed: ${n instanceof Error?n.message:String(n)}`),n}}async post(e,o,n){try{return r.debug(`POST request to: ${e}`),(await this.client.post(e,o,n)).data}catch(s){throw r.debug(`POST request failed: ${s instanceof Error?s.message:String(s)}`),s}}async put(e,o,n){try{return r.debug(`PUT request to: ${e}`),(await this.client.put(e,o,n)).data}catch(s){throw r.debug(`PUT request failed: ${s instanceof Error?s.message:String(s)}`),s}}async delete(e,o){try{return r.debug(`DELETE request to: ${e}`),(await this.client.delete(e,o)).data}catch(n){throw r.debug(`DELETE request failed: ${n instanceof Error?n.message:String(n)}`),n}}async patch(e,o,n){try{return r.debug(`PATCH request to: ${e}`),(await this.client.patch(e,o,n)).data}catch(s){throw r.debug(`PATCH request failed: ${s instanceof Error?s.message:String(s)}`),s}}};r.debug(`Initializing API client with URL: ${Me}`);var $=new Ue(Me);import{z as i}from"zod";import{INVALID as wr,ParseStatus as Er,ZodIssueCode as J,ZodParsedType as it,ZodType as xr,addIssueToContext as Q,z as at}from"zod";var Tr="ZodDecimal",$r=/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/,ce=class extends xr{_parse(e){if(e.data!==null&&typeof e.data=="object"&&"toNumber"in e.data&&(e.data=e.data.toNumber()),this._def.coerce&&(e.data=Number(e.data)),this._getType(e)!==it.number){let c=this._getOrReturnCtx(e);return Q(c,{code:J.invalid_type,expected:it.number,received:c.parsedType}),wr}let n,s=new Er;for(let c of this._def.checks)if(c.kind==="precision"){let a=e.data.toString().match($r);Math.max((a[1]?a[1].length:0)-(a[2]?parseInt(a[2],10):0),0)>c.value&&(n=this._getOrReturnCtx(e,n),Q(n,{code:J.custom,message:c.message,params:{precision:c.value}}),s.dirty())}else c.kind==="wholeNumber"?e.data.toString().split(".")[0].length>c.value&&(n=this._getOrReturnCtx(e,n),Q(n,{code:J.custom,message:c.message,params:{wholeNumber:c.value}}),s.dirty()):c.kind==="min"?(c.inclusive?e.data<c.value:e.data<=c.value)&&(n=this._getOrReturnCtx(e,n),Q(n,{code:J.too_small,minimum:c.value,type:"number",inclusive:c.inclusive,exact:!1,message:c.message}),s.dirty()):c.kind==="max"?(c.inclusive?e.data>c.value:e.data>=c.value)&&(n=this._getOrReturnCtx(e,n),Q(n,{code:J.too_big,maximum:c.value,type:"number",inclusive:c.inclusive,exact:!1,message:c.message}),s.dirty()):c.kind==="finite"&&(Number.isFinite(e.data)||(n=this._getOrReturnCtx(e,n),Q(n,{code:J.not_finite,message:c.message}),s.dirty()));return{status:s.value,value:e.data}}setLimit(e,o,n,s){return new ce({...this._def,checks:[...this._def.checks,{kind:e,value:o,inclusive:n,message:s}]})}_addCheck(e){return new ce({...this._def,checks:[...this._def.checks,e]})}lte(e,o){return this.setLimit("max",e,!0,o)}lt(e,o){return this.setLimit("max",e,!1,o)}max=this.lte;gt(e,o){return this.setLimit("min",e,!1,o)}gte(e,o){return this.setLimit("min",e,!0,o)}min=this.gte;precision(e,o){return this._addCheck({kind:"precision",value:e,message:o})}wholeNumber(e,o){return this._addCheck({kind:"wholeNumber",value:e,message:o})}get minValue(){let e=null;for(let o of this._def.checks)o.kind==="min"&&(e===null||o.value>e)&&(e=o.value);return e}get maxValue(){let e=null;for(let o of this._def.checks)o.kind==="max"&&(e===null||o.value<e)&&(e=o.value);return e}positive(e){return this._addCheck({kind:"min",value:0,inclusive:!1,message:e})}negative(e){return this._addCheck({kind:"max",value:0,inclusive:!1,message:e})}nonpositive(e){return this._addCheck({kind:"max",value:0,inclusive:!0,message:e})}nonnegative(e){return this._addCheck({kind:"min",value:0,inclusive:!0,message:e})}finite(e){return this._addCheck({kind:"finite",message:e})}safe(e){return this._addCheck({kind:"min",inclusive:!0,value:Number.MIN_SAFE_INTEGER,message:e})._addCheck({kind:"max",inclusive:!0,value:Number.MAX_SAFE_INTEGER,message:e})}get isFinite(){let e=null,o=null;for(let n of this._def.checks){if(n.kind==="finite")return!0;n.kind==="min"?(o===null||n.value>o)&&(o=n.value):n.kind==="max"&&(e===null||n.value<e)&&(e=n.value)}return Number.isFinite(o)&&Number.isFinite(e)}},X=ce;Ye(X,"create",e=>new ce({checks:[],typeName:Tr,coerce:e?.coerce??!1}));var ct=at.object({template:at.string().min(1,"Template cannot be empty")});var Pr=i.object({password:i.string(),registry:i.string().nullable(),username:i.string()}),Dr=i.object({docker_compose_file:i.string(),docker_config:Pr.optional(),features:i.array(i.string()),kms_enabled:i.boolean(),manifest_version:i.number(),name:i.string(),public_logs:i.boolean(),public_sysinfo:i.boolean(),runner:i.string().optional(),salt:i.string().nullable().optional(),tproxy_enabled:i.boolean(),version:i.string().optional()}),Ar=i.object({name:i.string(),image:i.string(),compose_file:Dr,vcpu:i.number(),memory:i.number(),disk_size:i.number(),ports:i.array(i.any())}),Ir=i.object({id:i.string(),name:i.string(),status:i.string(),uptime:i.string(),app_url:i.string(),app_id:i.string(),instance_id:i.string(),configuration:Ar,exited_at:i.string(),boot_progress:i.string(),boot_error:i.string(),shutdown_progress:i.string(),image_version:i.string()}),Rr=i.object({id:i.number(),username:i.string()}),Fr=i.object({id:i.number(),name:i.string()}),ze=i.object({hosted:Ir,name:i.string(),managed_user:Rr,node:Fr,listed:i.boolean(),status:i.string(),in_progress:i.boolean(),dapp_dashboard_url:i.string().nullable(),syslog_endpoint:i.string(),allow_upgrade:i.boolean()}),me=i.object({id:i.number(),name:i.string(),status:i.string(),teepod_id:i.number().nullable(),teepod:i.object({id:i.number(),name:i.string()}).nullable(),user_id:i.number(),app_id:i.string(),vm_uuid:i.string().nullable(),instance_id:i.string().nullable(),app_url:i.string().nullable(),base_image:i.string(),vcpu:i.number(),memory:i.number(),disk_size:i.number(),manifest_version:i.number(),version:i.string(),runner:i.string(),docker_compose_file:i.string(),features:i.array(i.string()).nullable(),created_at:i.string(),encrypted_env_pubkey:i.string()}),mt=i.object({app_env_encrypt_pubkey:i.string(),app_id_salt:i.string()}),lt=i.object({id:i.number(),teepod_id:i.number().nullable(),teepod:i.object({id:i.number(),name:i.string()}).nullable(),name:i.string(),status:i.string(),in_progress:i.boolean(),app_id:i.string(),vm_uuid:i.string(),instance_id:i.string().nullable(),vcpu:i.number(),memory:i.number(),disk_size:i.number(),base_image:i.string(),encrypted_env_pubkey:i.string(),listed:i.boolean(),project_id:i.string(),project_type:i.string().nullable()}),pt=i.object({username:i.string(),email:i.string(),credits:X.create({coerce:!0}),granted_credits:X.create({coerce:!0}),role:i.string(),avatar:i.string(),flag_reset_password:i.boolean(),team_name:i.string(),team_tier:i.string(),trial_ended_at:i.string().nullable()}),un=i.array(ze),dt=i.object({detail:i.string()}),fn=i.object({key:i.string(),value:i.string()}),ut=i.object({name:i.string(),description:i.string().optional(),version:i.array(i.number()).optional(),is_dev:i.boolean().optional(),rootfs_hash:i.string().optional(),shared_ro:i.boolean().optional(),cmdline:i.string().optional(),kernel:i.string().optional(),initrd:i.string().optional(),hda:i.string().nullable().optional(),rootfs:i.string().optional(),bios:i.string().optional()}),Mr=i.object({teepod_id:i.number().nullable(),name:i.string(),listed:i.boolean(),resource_score:i.number(),remaining_vcpu:i.number(),remaining_memory:i.number(),remaining_cvm_slots:i.number(),images:i.array(ut).optional()}),Vr=i.object({max_instances:i.number().nullable(),max_vcpu:i.number().nullable(),max_memory:i.number().nullable(),max_disk:i.number().nullable()}),ft=i.object({tier:i.string(),capacity:Vr,nodes:i.array(Mr)}),Lr=i.object({is_online:i.boolean(),is_public:i.boolean(),error:i.string().nullable(),internal_ip:i.string(),latest_handshake:i.string(),public_urls:i.array(i.object({app:i.string(),instance:i.string()}))}),gt=i.object({is_online:i.boolean(),is_public:i.boolean(),error:i.string().nullable(),app_certificates:i.array(i.object({subject:i.object({common_name:i.string().nullable(),organization:i.string().nullable(),country:i.string().nullable(),state:i.string().nullable().optional(),locality:i.string().nullable().optional()}),issuer:i.object({common_name:i.string().nullable(),organization:i.string().nullable(),country:i.string().nullable()}),serial_number:i.string(),not_before:i.string(),not_after:i.string(),version:i.string(),fingerprint:i.string(),signature_algorithm:i.string(),sans:i.string().nullable(),is_ca:i.boolean(),position_in_chain:i.number(),quote:i.string().nullable()})).nullable(),tcb_info:i.object({mrtd:i.string(),rootfs_hash:i.string(),rtmr0:i.string(),rtmr1:i.string(),rtmr2:i.string(),rtmr3:i.string(),event_log:i.array(i.object({imr:i.number(),event_type:i.number(),digest:i.string(),event:i.string(),event_payload:i.string()}))}).nullable(),compose_file:i.string().nullable()});function ht(t){try{return JSON.stringify(t)}catch(e){return e instanceof Error&&e.message.includes("cyclic")?"[Cyclic Object]":String(t)}}async function W(){try{r.debug(`Fetching user info from ${x.USER_INFO}`);let t=await $.get(x.USER_INFO);r.debug(`Received response: ${ht(t)}`);try{return pt.parse(t)}catch(e){throw r.error(`Failed to parse user info response: ${e}`),r.debug(`Response structure: ${ht(t)}`),e}}catch(t){throw r.error(`Failed to get user info: ${t instanceof Error?t.message:String(t)}`),new Error(`Failed to get user info: ${t instanceof Error?t.message:String(t)}`)}}var yt=new Nr().name("login").description("Set the API key for authentication").argument("[api-key]","Phala Cloud API key to set").action(async t=>{try{let e;if(!t)t=(await Or({type:"password",name:"apiKey",message:"Enter your API key:",validate:async n=>{if(n.length===0)return"API key cannot be empty";try{if(await Re(n),e=await W(),!e.username)return await ie(),"Invalid API key"}catch{return"Invalid API key"}return!0}})).apiKey;else if(await Re(t),e=await W(),!e.username)return await ie(),"Invalid API key";r.success(`Welcome ${e.username}! API key validated and saved successfully`),r.break(),r.info(`Open in Web UI at ${w}/dashboard/`)}catch(e){r.error(`Failed to set API key: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}});import{Command as Ur}from"commander";var bt=new Ur().name("logout").description("Remove the stored API key").action(async()=>{try{await ie(),r.success("API key removed successfully")}catch(t){r.error(`Failed to remove API key: ${t instanceof Error?t.message:String(t)}`),process.exit(1)}});import{Command as zr}from"commander";var vt=new zr().name("status").description("Check authentication status").option("-j, --json","Output in JSON format").option("-d, --debug","Enable debug output").action(async t=>{try{t.debug&&(process.env.DEBUG="true");let e=await Z();if(!e){r.warn('Not authenticated. Please set an API key with "phala auth login"');return}r.debug(`Using API key: ${e.substring(0,5)}...`);let o=r.startSpinner("Checking authentication status");try{let n=await W();if(o.stop(!0),t.json){console.log(JSON.stringify(n,null,2));return}r.break(),r.success(`Authenticated as ${n.username}`);let s={Username:n.username,Email:n.email,Role:n.role,Team:`${n.team_name} (${n.team_tier})`,Credits:`$${(n.credits+n.granted_credits).toFixed(2)}`};n.trial_ended_at&&(s["Trial Ended At"]=n.trial_ended_at),r.keyValueTable(s,{borderStyle:"rounded"})}catch(n){o.stop(!1),r.error("Authentication failed. Your API key may be invalid or expired."),r.info('Please set a new API key with "phala auth login"'),t.debug&&r.debug(`Error details: ${n instanceof Error?n.message:String(n)}`)}}catch(e){r.error(`Failed to check authentication status: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}});var Ct=new jr().name("auth").description("Authenticate with Phala Cloud").addCommand(yt).addCommand(bt).addCommand(vt);import{Command as no}from"commander";import{Command as Qr}from"commander";import{execa as Gr}from"execa";import O from"node:fs";import pe from"node:path";import Hr from"handlebars";import{exec as qr,spawn as Yr}from"node:child_process";import{promisify as Zr}from"node:util";import Et from"node:os";import Wr from"inquirer";import je from"node:fs";import We from"node:path";function B(t,e=process.cwd()){let o=We.resolve(e,t);if(!je.existsSync(o))throw new Error(`File not found at ${o}`);return!0}async function K(t,e,o="file",n=process.cwd()){return(await Wr.prompt([{type:"input",name:o,message:t,default:e,validate:c=>{let a=We.resolve(n,c);return je.existsSync(a)?!0:`File not found at ${a}`}}]))[o]}function Ce(t,e){for(let o of t){let n=We.join(process.cwd(),o);if(je.existsSync(n))return e?r.info(e.replace("{path}",n)):r.info(`File detected: ${n}`),o}}import*as R from"node:fs";import*as z from"node:path";import*as ee from"node:os";import{execSync as te,spawn as Br}from"node:child_process";import*as Be from"node:net";var A={version:"0.1.4",baseUrl:"https://github.com/Leechael/tappd-simulator/releases/download/v0.1.4",installDir:z.join(ee.homedir(),".phala-cloud","tappd-simulator"),defaultLogPath:z.join(ee.homedir(),".phala-cloud","logs","tappd-simulator.log"),platforms:{darwin:{filename:"tappd-simulator-0.1.4-aarch64-apple-darwin.tgz",extractedFolder:"tappd-simulator-0.1.4-aarch64-apple-darwin",socketArg:"unix:/tmp/tappd.sock"},linux:{filename:"tappd-simulator-0.1.4-x86_64-linux-musl.tgz",extractedFolder:"tappd-simulator-0.1.4-x86_64-linux-musl",socketArg:"unix:/tmp/tappd.sock"},win32:{filename:"tappd-simulator-0.1.4-x86_64-pc-windows-msvc.tgz",extractedFolder:"tappd-simulator-0.1.4-x86_64-pc-windows-msvc",socketArg:"127.0.0.1:8090"}}};function kt(){try{if(!R.existsSync(A.installDir))return!1;let t=ee.platform();if(!A.platforms[t])throw new Error(`Unsupported platform: ${t}`);let e=z.join(A.installDir,A.platforms[t].extractedFolder);if(!R.existsSync(e))return!1;let n=z.join(e,t==="win32"?"tappd-simulator.exe":"tappd-simulator");return R.existsSync(n)}catch(t){return r.error("Error checking if simulator is installed:",t),!1}}function le(){let t=ee.platform();if(!A.platforms[t])throw new Error(`Unsupported platform: ${t}. Only darwin, linux, and win32 are supported.`);return t}async function _t(t){let e=o=>{r.info(o),t&&t(o)};try{let o=le(),n=A.platforms[o];R.existsSync(A.installDir)||(r.info(`Creating installation directory at ${A.installDir}`),R.mkdirSync(A.installDir,{recursive:!0})),process.chdir(A.installDir);let s=`${A.baseUrl}/${n.filename}`;r.info(`Downloading simulator from ${s}`),te(`wget ${s}`,{stdio:"inherit"}),r.info(`Extracting ${n.filename}`),te(`tar -xvf ${n.filename}`,{stdio:"inherit"}),r.success("Simulator installation completed successfully")}catch(o){throw r.error("Error installing simulator:",o),new Error(`Failed to install simulator: ${o}`)}}async function St(t={}){try{let e=le(),o=A.platforms[e],n=z.join(A.installDir,o.extractedFolder);process.chdir(n);let s=e==="win32"?"tappd-simulator.exe":"./tappd-simulator",c={background:t.background??!0,logToFile:t.logToFile??!0,logFilePath:t.logFilePath??A.defaultLogPath};if(c.logToFile){let p=z.dirname(c.logFilePath);R.existsSync(p)||R.mkdirSync(p,{recursive:!0}),r.info(`Simulator logs will be written to: ${c.logFilePath}`)}r.info(`Starting simulator with: ${s} -l ${o.socketArg}`);let a="inherit",u=null;c.logToFile&&(u=R.createWriteStream(c.logFilePath,{flags:"a"}),a=["ignore",u,u]);let y=Br(s,["-l",o.socketArg],{stdio:a,shell:e==="win32",detached:c.background});if(u){let p=new Date().toISOString();u.write(`
|
102
103
|
[${p}] Simulator started
|
103
104
|
`)}return c.background&&(y.unref(),r.success("Simulator is running in the background")),await Ke(),y}catch(e){throw r.error("Error running simulator:",e),new Error(`Failed to run simulator: ${e}`)}}async function ke(){try{let t=le(),e=A.platforms[t];if(t==="darwin"||t==="linux"){let o="/tmp/tappd.sock";return R.existsSync(o)?new Promise(n=>{let s=Be.createConnection({path:o}).on("connect",()=>{s.end(),n(!0)}).on("error",()=>{n(!1)});setTimeout(()=>{s.end(),n(!1)},1e3)}):!1}if(t==="win32"){let o="127.0.0.1";return new Promise(s=>{let c=Be.createConnection({host:o,port:8090}).on("connect",()=>{c.end(),s(!0)}).on("error",()=>{s(!1)});setTimeout(()=>{c.end(),s(!1)},1e3)})}return!1}catch(t){return r.error("Error checking if simulator is running:",t),!1}}async function wt(){try{let t=le();if(!await ke())return r.info("Simulator is not running"),!0;r.info("Stopping simulator..."),t==="win32"?te(`for /f "tokens=5" %a in ('netstat -ano ^| findstr :8080') do taskkill /F /PID %a`,{stdio:"inherit"}):te("pkill -f tappd-simulator",{stdio:"inherit"});let e=!await ke();return e?r.success("Simulator stopped successfully"):r.error("Failed to stop simulator"),await G(),e}catch(t){return r.error("Error stopping simulator:",t),!1}}function Kr(){return le()==="win32"?"http://127.0.0.1:8090":"unix:///tmp/tappd.sock"}async function Ke(t){try{let e=Kr(),o=t||e;return await te(`export DSTACK_SIMULATOR_ENDPOINT=${o}`),r.success(`Setting DSTACK_SIMULATOR_ENDPOINT=${o} for current process`),t}catch(e){throw r.error("Error setting simulator endpoint environment variable:",e),new Error(`Failed to set simulator endpoint: ${e}`)}}async function G(){return await te("unset DSTACK_SIMULATOR_ENDPOINT"),r.debug("Deleted DSTACK_SIMULATOR_ENDPOINT from current process"),!0}var de=Zr(qr),xt=".phala-cloud/logs",Jr=".phala-cloud/compose",Tt=10,P=class{username;image;registry;constructor(e,o,n){this.image=e,this.username=o||"",this.registry=n||""}ensureLogsDir(){let e=pe.resolve(xt);O.existsSync(e)||O.mkdirSync(e,{recursive:!0})}getLogFilePath(e,o){let n=new Date().toISOString().replace(/[:.]/g,"-");return pe.resolve(xt,`${o||this.image}-${e}-${n}.log`)}getSystemArchitecture(){let e=Et.arch();switch(e){case"arm":case"arm64":return"arm64";case"x64":return"amd64";default:return e}}spawnProcess(e,o,n,s){return new Promise((c,a)=>{let u=Yr(e,o);this.ensureLogsDir();let y=this.getLogFilePath(n,s),p=O.createWriteStream(y,{flags:"a"}),b=[],k=(m,l=!1)=>{let g=m.toString().split(`
|
104
105
|
`);p.write(m);for(let d of g)if(d.trim()){b.push(d),b.length>Tt&&b.shift(),console.clear(),console.log(`Latest ${Tt} lines (full log at ${y}):`),console.log("-".repeat(50));for(let v of b)l?console.error(v):console.log(v)}};u.stdout.on("data",m=>k(m)),u.stderr.on("data",m=>k(m,!0)),u.on("close",m=>{p.end(),m===0?(console.log(`
|
@@ -133,5 +134,5 @@ services:
|
|
133
134
|
- "80:80"
|
134
135
|
`,pr={jupyter:{compose:$o,name:"Jupyter Notebook"},httpbin:{compose:Po,name:"HTTPBin"}};import{encryptEnvVars as Ao}from"@phala/dstack-sdk/encrypt-env-vars";import dr from"inquirer";import Io from"node:crypto";var ur=new Do().name("demo").description("Demo commands to launch a demo on Phala Cloud").action(async()=>{try{await Z()||(r.error("You need to be logged in to use the demo command"),r.info("Please login with: phala auth login"),process.exit(1));try{let g=r.startSpinner("Verifying your credentials"),d=await W();g.stop(!0),r.success(`Logged in as ${d.username}`)}catch{r.error("Authentication failed. Your API key may be invalid or expired."),r.info("Please set a new API key with: phala auth login"),process.exit(1)}let e=Object.values(pr);e.length===0&&(r.error("No template files found in the templates directory"),process.exit(1));let{selectedTemplate:o}=await dr.prompt([{type:"list",name:"selectedTemplate",message:"Select a template to deploy:",choices:e.map(g=>({name:g.name,value:g}))}]),n=o.compose;r.success(`Selected template: ${o.name}`);let s=Io.randomBytes(16).toString("hex"),c=H([`TOKEN=${s}`],""),{cvmName:a}=await dr.prompt([{type:"input",name:"cvmName",message:"Enter a name for your CVM:",default:`${o.name.replace(" ","-")}`,validate:g=>g.trim()?!0:"CVM name is required"}]);r.info("Preparing to deploy your CVM...");let u={teepod_id:3,name:a,image:ae,vcpu:2,memory:2048,disk_size:20,compose_manifest:{docker_compose_file:n,docker_config:{url:"",username:"",password:""},features:["kms","tproxy-net"],kms_enabled:!0,manifest_version:2,name:a,public_logs:!0,public_sysinfo:!0,tproxy_enabled:!0},listed:!1},y=r.startSpinner("Preparing CVM configuration"),p=await Ee(u);y.stop(!0),p||(r.error("Failed to prepare CVM configuration"),process.exit(1));let b=await Ao(c,p.app_env_encrypt_pubkey);r.debug("Public key:",p.app_env_encrypt_pubkey),r.debug("Encrypted environment variables:",b);let k=r.startSpinner("Creating your demo CVM"),m=await xe({...u,encrypted_env:b,app_env_encrypt_pubkey:p.app_env_encrypt_pubkey,app_id_salt:p.app_id_salt});k.stop(!0),m||(r.error("Failed to create demo CVM"),process.exit(1)),r.success("Demo CVM created successfully! \u{1F389}"),r.break();let l={"CVM ID":m.id,Name:m.name,Status:m.status,"App ID":`app_${m.app_id}`,"App URL":m.app_url?m.app_url:`${w}/dashboard/cvms/app_${m.app_id}`,Template:o.name,Resources:"2 vCPUs, 2GB RAM, 20GB Storage"};o.name.includes("Jupyter Notebook")&&(l["Jupyter Token"]=s,l["Access Instructions"]="Access your Jupyter notebook using the token above. Go to 'Network' tab to see the public URL."),r.keyValueTable(l,{borderStyle:"rounded"}),r.break(),r.success(`Your demo is being created. You can check its status with:
|
135
136
|
phala cvms get app_${m.app_id}`)}catch(t){r.error(`Failed to launch demo: ${t instanceof Error?t.message:String(t)}`),process.exit(1)}});process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));async function Fo(){new Ro().name("phala").alias("pha").description(`${be}
|
136
|
-
Phala Cloud CLI - Manage your Phala Cloud Deployments`).version("v1.0.
|
137
|
+
Phala Cloud CLI - Manage your Phala Cloud Deployments`).version("v1.0.15").addCommand(Ct).addCommand(ar).addCommand(Mt).addCommand(Nt).addCommand(ur).addCommand(lr).parse(process.argv)}Fo().catch(t=>{r.error("An error occurred:",t),process.exit(1)});
|
137
138
|
//# sourceMappingURL=index.js.map
|