@sinch/cli 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +228 -228
  3. package/bin/sinch +4 -4
  4. package/dist/index.js +34 -34
  5. package/package.json +79 -79
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Po=Object.create;var Rt=Object.defineProperty;var Ao=Object.getOwnPropertyDescriptor;var Eo=Object.getOwnPropertyNames;var xo=Object.getPrototypeOf,Do=Object.prototype.hasOwnProperty;var Q=(s,e)=>()=>(s&&(e=s(s=0)),e);var R=(s,e)=>()=>(e||s((e={exports:{}}).exports,e),e.exports),ut=(s,e)=>{for(var n in e)Rt(s,n,{get:e[n],enumerable:!0})},Vn=(s,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Eo(e))!Do.call(s,o)&&o!==n&&Rt(s,o,{get:()=>e[o],enumerable:!(i=Ao(e,o))||i.enumerable});return s};var h=(s,e,n)=>(n=s!=null?Po(xo(s)):{},Vn(e||!s||!s.__esModule?Rt(n,"default",{value:s,enumerable:!0}):n,s)),M=s=>Vn(Rt({},"__esModule",{value:!0}),s);var zt=R((ba,jo)=>{jo.exports={name:"@sinch/cli",version:"0.2.0",description:"Official Sinch CLI - Manage all Sinch products from your terminal",main:"dist/index.js",bin:{sinch:"bin/sinch"},scripts:{start:"tsx src/index.ts",dev:"tsx watch src/index.ts",build:"tsc && node scripts/post-build.js","build:prod":"tsup src/index.ts --format cjs --dts --clean --minify",typecheck:"tsc --noEmit",test:"jest --config jest.config.js && jest --config tests/e2e/jest.config.js","test:unit":"jest --config jest.config.js","test:e2e":"jest --config tests/e2e/jest.config.js","test:e2e:staging":"jest --config tests/e2e/jest.config.js --env=staging",prepublishOnly:"npm run build:prod",format:"prettier --write .","format:check":"prettier --check ."},keywords:[],author:"Sinch <support@sinch.com> (https://www.sinch.com)",license:"MIT",private:!1,publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},homepage:"https://www.sinch.com/products/apis/voice/",files:["dist/","bin/","README.md","LICENSE"],dependencies:{"@inquirer/prompts":"^8.2.0","@sinch/fax":"^1.0.0","@sinch/sdk-core":"^1.2.1","adm-zip":"^0.5.10",axios:"^1.13.3",blessed:"^0.1.81",chalk:"^4.1.2",chokidar:"^3.6.0","cli-spinners":"^2.9.2","cli-table3":"^0.6.3",clipboardy:"^5.1.0",commander:"^14.0.0",eventsource:"^4.0.0","form-data":"^4.0.0","fs-extra":"^11.3.3",inquirer:"8.2.7",keytar:"^7.9.0",ora:"^4.1.1"},devDependencies:{"@types/adm-zip":"^0.5.7","@types/blessed":"^0.1.25","@types/fs-extra":"^11.0.4","@types/inquirer":"^9.0.9","@types/jest":"^30.0.0","@types/keytar":"^4.4.0","@types/node":"24.10.9",execa:"^5.1.1",jest:"^30.0.0",nodemon:"^3.0.1",prettier:"^3.8.1","ts-jest":"^29.4.6",tsup:"^8.5.0",tsx:"^4.20.4",typescript:"^5.9.2"},engines:{node:">=20.0.0",npm:">=9.0.0"}}});function Nt(s){if(!s)return s;let e=s;for(let n of Jo)e=e.replace(n,i=>{let o=i.match(/^[A-Za-z]+\s+/)?.[0]||"";return o?`${o}[REDACTED]`:"[REDACTED]"});return e}function zn(s){let e={...s};if(e.Authorization){let o=e.Authorization.match(/^([A-Za-z]+)\s+/),r=o?o[1]:"Bearer";e.Authorization=`${r} [REDACTED]`}let n=["x-api-key","x-auth-token","api-key","token"];for(let i of n){let o=Object.keys(e).find(r=>r.toLowerCase()===i);o&&(e[o]="[REDACTED]")}return e}var Jo,Wn=Q(()=>{"use strict";Jo=[/Bearer\s+[A-Za-z0-9\-_.]+/g,/Basic\s+[A-Za-z0-9+/=]+/g,/[Aa]uthorization["\s:=]+["']?[^"'\s]+/g]});var Xe={};ut(Xe,{SinchAPI:()=>T});var Ot,Yt,Ue,T,z=Q(()=>{"use strict";Ot=h(require("axios")),Yt=h(require("form-data")),Ue=h(require("chalk"));Wn();T=class{baseUrl;oauthUrl;projectId;timeout;credentials;client;constructor(e={}){this.baseUrl=e.apiUrl||"https://functions.api.sinch.com/",this.oauthUrl=e.oauthUrl||"https://auth.sinch.com/oauth2/token",this.projectId=e.projectId||"",this.timeout=6e4,this.credentials=e.credentials||null,this.client=Ot.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"User-Agent":"sinch-functions-cli/1.0.0"}}),this.client.interceptors.request.use(async n=>{if(this.credentials){let i=await this.getValidToken();i&&(n.headers.Authorization=`${i.token_type} ${i.access_token}`)}if(process.env.DEBUG_HTTP){let i=Nt(n.url||"");if(console.log(Ue.default.gray(`\u2192 ${n.method?.toUpperCase()} ${i}`)),process.env.DEBUG_HTTP==="2"||process.env.DEBUG_HTTP==="verbose"){let o=zn(n.headers);console.log(Ue.default.gray(" Headers:"),JSON.stringify(o,null,2))}}return n},n=>Promise.reject(n)),this.client.interceptors.response.use(n=>{if(process.env.DEBUG_HTTP){let i=Nt(n.config.url||"");console.log(Ue.default.gray(`\u2190 ${n.status} ${i}`))}return n},async n=>{if(process.env.DEBUG_HTTP){let i=Nt(n.config?.url||"");console.log(Ue.default.red(`\u2190 ${n.response?.status||"ERROR"} ${i}`))}if(n.response?.status===401&&this.credentials&&n.config){let i=n.config;if(!i._retry){i._retry=!0;try{let o=await this.getValidToken();if(o)return i.headers.Authorization=`${o.token_type} ${o.access_token}`,this.client.request(i)}catch{console.error(Ue.default.yellow("Token refresh failed during retry"))}}}return Promise.reject(n)})}async listAllTemplates(e=null){try{let n=e?{category:e}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates`,{params:n})).data}catch(n){throw this._handleError(n,"Failed to list templates")}}async listRuntimeTemplates(e,n=null){try{let i=n?{category:n}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}`,{params:i})).data}catch(i){throw this._handleError(i,`Failed to list ${e} templates`)}}async getTemplateDetails(e,n){try{return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}`)).data}catch(i){throw this._handleError(i,`Failed to get template details for ${e}/${n}`)}}async downloadTemplate(e,n){try{let i=await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}/download`,{responseType:"arraybuffer"});return Buffer.from(i.data)}catch(i){throw this._handleError(i,`Failed to download template ${e}/${n}`)}}async listFunctions(){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions`)).data}catch(e){throw this._handleError(e,"Failed to list functions")}}async getFunction(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}`)).data}catch(n){throw this._handleError(n,`Failed to get function ${e}`)}}async deployFunction(e,n,i,o,r="public"){try{let a=new Yt.default;return a.append("name",e),a.append("runtime",n),a.append("code",i,{filename:"function.zip"}),a.append("accessLevel",r),o&&a.append("configuration",JSON.stringify(o)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,a,{headers:{...a.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(a){throw this._handleError(a,"Failed to deploy function")}}async updateFunction(e,n,i){try{let o=new Yt.default;return o.append("code",n,{filename:"function.zip"}),i&&o.append("configuration",JSON.stringify(i)),(await this.client.put(`/v1/projects/${this.projectId}/functions/${e}`,o,{headers:{...o.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(o){throw this._handleError(o,`Failed to update function ${e}`)}}async deleteFunction(e){try{await this.client.delete(`/v1/projects/${this.projectId}/functions/${e}`)}catch(n){throw this._handleError(n,`Failed to delete function ${e}`)}}async downloadFunction(e){try{let n=await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/download`,{responseType:"arraybuffer"});return Buffer.from(n.data)}catch(n){throw this._handleError(n,`Failed to download function ${e}`)}}async getFunctionLogs(e,n={}){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/logs`,{params:n})).data}catch(i){throw this._handleError(i,`Failed to get logs for function ${e}`)}}async getFunctionStatus(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/deployment/status`)).data}catch(n){throw this._handleError(n,`Failed to get status for function ${e}`)}}async generateDocumentationFromCode(e,n="node",i="function"){try{return(await this.client.post(`/v1/projects/${this.projectId}/test/documentation`,{Code:e,Runtime:n,Name:i})).data}catch(o){throw this._handleError(o,"Failed to generate documentation from code")}}async generateDocumentationForFunction(e,n){try{let i=n?{MarkdownOverride:n}:{};return(await this.client.post(`/v1/projects/${this.projectId}/functions/${e}/documentation`,i)).data}catch(i){throw this._handleError(i,`Failed to generate documentation for function ${e}`)}}async getDocumentationForFunction(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/documentation`)).data}catch(n){throw this._handleError(n,`Failed to get documentation for function ${e}`)}}async streamDeployment(e,n,i){let o=p=>p.status?"status":p.progress?"progress":p.completed?"completed":p.failed||p.error?"failed":p.connected?"connected":"message",r=new URL(`v1/projects/${this.projectId}/functions/${e}/deployment/stream`,this.baseUrl).href,a={Accept:"text/event-stream","Cache-Control":"no-cache"};if(this.credentials)try{let p=await this.credentials.retrieve();if(p&&p.keyId&&p.keySecret){let d=Buffer.from(`${p.keyId}:${p.keySecret}`).toString("base64");a.Authorization=`Basic ${d}`}}catch(p){console.error("Failed to add authentication:",p)}let l=null;try{l=new AbortController;let p=await fetch(r,{method:"GET",headers:a,signal:l.signal});if(!p.ok)throw new Error(`SSE connection failed: ${p.status} ${p.statusText}`);if(!p.body)throw new Error("Response body is null");let d=p.body.getReader(),f=new TextDecoder,g="";return(async()=>{let y="";try{for(;;){let{done:v,value:$}=await d.read();if(v)break;let P=f.decode($,{stream:!0});g+=P;let D=g.split(`
2
+ "use strict";var Ao=Object.create;var Rt=Object.defineProperty;var Eo=Object.getOwnPropertyDescriptor;var xo=Object.getOwnPropertyNames;var Do=Object.getPrototypeOf,jo=Object.prototype.hasOwnProperty;var Q=(s,e)=>()=>(s&&(e=s(s=0)),e);var R=(s,e)=>()=>(e||s((e={exports:{}}).exports,e),e.exports),ut=(s,e)=>{for(var n in e)Rt(s,n,{get:e[n],enumerable:!0})},Vn=(s,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of xo(e))!jo.call(s,o)&&o!==n&&Rt(s,o,{get:()=>e[o],enumerable:!(i=Eo(e,o))||i.enumerable});return s};var h=(s,e,n)=>(n=s!=null?Ao(Do(s)):{},Vn(e||!s||!s.__esModule?Rt(n,"default",{value:s,enumerable:!0}):n,s)),M=s=>Vn(Rt({},"__esModule",{value:!0}),s);var zt=R((Sa,Ro)=>{Ro.exports={name:"@sinch/cli",version:"0.2.1",description:"Official Sinch CLI - Manage all Sinch products from your terminal",main:"dist/index.js",bin:{sinch:"bin/sinch"},scripts:{start:"tsx src/index.ts",dev:"tsx watch src/index.ts",build:"tsc && node scripts/post-build.js","build:prod":"tsup src/index.ts --format cjs --dts --clean --minify",typecheck:"tsc --noEmit",test:"jest --config jest.config.js && jest --config tests/e2e/jest.config.js","test:unit":"jest --config jest.config.js","test:e2e":"jest --config tests/e2e/jest.config.js","test:e2e:staging":"jest --config tests/e2e/jest.config.js --env=staging",prepublishOnly:"npm run build:prod",format:"prettier --write .","format:check":"prettier --check ."},keywords:[],author:"Sinch <support@sinch.com> (https://www.sinch.com)",license:"MIT",private:!1,publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},homepage:"https://www.sinch.com/products/apis/voice/",files:["dist/","bin/","README.md","LICENSE"],dependencies:{"@inquirer/prompts":"^8.2.0","@sinch/fax":"^1.0.0","@sinch/sdk-core":"^1.2.1","adm-zip":"^0.5.10",axios:"^1.13.3",blessed:"^0.1.81",chalk:"^4.1.2",chokidar:"^3.6.0","cli-spinners":"^2.9.2","cli-table3":"^0.6.3",clipboardy:"^5.1.0",commander:"^14.0.0",eventsource:"^4.0.0","form-data":"^4.0.0","fs-extra":"^11.3.3",inquirer:"8.2.7",keytar:"^7.9.0",ora:"^4.1.1"},devDependencies:{"@types/adm-zip":"^0.5.7","@types/blessed":"^0.1.25","@types/fs-extra":"^11.0.4","@types/inquirer":"^9.0.9","@types/jest":"^30.0.0","@types/keytar":"^4.4.0","@types/node":"24.10.9",execa:"^5.1.1",jest:"^30.0.0",nodemon:"^3.0.1",prettier:"^3.8.1","ts-jest":"^29.4.6",tsup:"^8.5.0",tsx:"^4.20.4",typescript:"^5.9.2"},engines:{node:">=20.0.0",npm:">=9.0.0"}}});function Nt(s){if(!s)return s;let e=s;for(let n of Bo)e=e.replace(n,i=>{let o=i.match(/^[A-Za-z]+\s+/)?.[0]||"";return o?`${o}[REDACTED]`:"[REDACTED]"});return e}function zn(s){let e={...s};if(e.Authorization){let o=e.Authorization.match(/^([A-Za-z]+)\s+/),r=o?o[1]:"Bearer";e.Authorization=`${r} [REDACTED]`}let n=["x-api-key","x-auth-token","api-key","token"];for(let i of n){let o=Object.keys(e).find(r=>r.toLowerCase()===i);o&&(e[o]="[REDACTED]")}return e}var Bo,Wn=Q(()=>{"use strict";Bo=[/Bearer\s+[A-Za-z0-9\-_.]+/g,/Basic\s+[A-Za-z0-9+/=]+/g,/[Aa]uthorization["\s:=]+["']?[^"'\s]+/g]});var Xe={};ut(Xe,{SinchAPI:()=>T});var Ot,Yt,Ue,T,z=Q(()=>{"use strict";Ot=h(require("axios")),Yt=h(require("form-data")),Ue=h(require("chalk"));Wn();T=class{baseUrl;oauthUrl;projectId;timeout;credentials;client;constructor(e={}){this.baseUrl=e.apiUrl||"https://functions.api.sinch.com/",this.oauthUrl=e.oauthUrl||"https://auth.sinch.com/oauth2/token",this.projectId=e.projectId||"",this.timeout=6e4,this.credentials=e.credentials||null,this.client=Ot.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"User-Agent":"sinch-functions-cli/1.0.0"}}),this.client.interceptors.request.use(async n=>{if(this.credentials){let i=await this.getValidToken();i&&(n.headers.Authorization=`${i.token_type} ${i.access_token}`)}if(process.env.DEBUG_HTTP){let i=Nt(n.url||"");if(console.log(Ue.default.gray(`\u2192 ${n.method?.toUpperCase()} ${i}`)),process.env.DEBUG_HTTP==="2"||process.env.DEBUG_HTTP==="verbose"){let o=zn(n.headers);console.log(Ue.default.gray(" Headers:"),JSON.stringify(o,null,2))}}return n},n=>Promise.reject(n)),this.client.interceptors.response.use(n=>{if(process.env.DEBUG_HTTP){let i=Nt(n.config.url||"");console.log(Ue.default.gray(`\u2190 ${n.status} ${i}`))}return n},async n=>{if(process.env.DEBUG_HTTP){let i=Nt(n.config?.url||"");console.log(Ue.default.red(`\u2190 ${n.response?.status||"ERROR"} ${i}`))}if(n.response?.status===401&&this.credentials&&n.config){let i=n.config;if(!i._retry){i._retry=!0;try{let o=await this.getValidToken();if(o)return i.headers.Authorization=`${o.token_type} ${o.access_token}`,this.client.request(i)}catch{console.error(Ue.default.yellow("Token refresh failed during retry"))}}}return Promise.reject(n)})}async listAllTemplates(e=null){try{let n=e?{category:e}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates`,{params:n})).data}catch(n){throw this._handleError(n,"Failed to list templates")}}async listRuntimeTemplates(e,n=null){try{let i=n?{category:n}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}`,{params:i})).data}catch(i){throw this._handleError(i,`Failed to list ${e} templates`)}}async getTemplateDetails(e,n){try{return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}`)).data}catch(i){throw this._handleError(i,`Failed to get template details for ${e}/${n}`)}}async downloadTemplate(e,n){try{let i=await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}/download`,{responseType:"arraybuffer"});return Buffer.from(i.data)}catch(i){throw this._handleError(i,`Failed to download template ${e}/${n}`)}}async listFunctions(){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions`)).data}catch(e){throw this._handleError(e,"Failed to list functions")}}async getFunction(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}`)).data}catch(n){throw this._handleError(n,`Failed to get function ${e}`)}}async deployFunction(e,n,i,o,r="public"){try{let a=new Yt.default;return a.append("name",e),a.append("runtime",n),a.append("code",i,{filename:"function.zip"}),a.append("accessLevel",r),o&&a.append("configuration",JSON.stringify(o)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,a,{headers:{...a.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(a){throw this._handleError(a,"Failed to deploy function")}}async updateFunction(e,n,i){try{let o=new Yt.default;return o.append("code",n,{filename:"function.zip"}),i&&o.append("configuration",JSON.stringify(i)),(await this.client.put(`/v1/projects/${this.projectId}/functions/${e}`,o,{headers:{...o.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(o){throw this._handleError(o,`Failed to update function ${e}`)}}async deleteFunction(e){try{await this.client.delete(`/v1/projects/${this.projectId}/functions/${e}`)}catch(n){throw this._handleError(n,`Failed to delete function ${e}`)}}async downloadFunction(e){try{let n=await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/download`,{responseType:"arraybuffer"});return Buffer.from(n.data)}catch(n){throw this._handleError(n,`Failed to download function ${e}`)}}async getFunctionLogs(e,n={}){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/logs`,{params:n})).data}catch(i){throw this._handleError(i,`Failed to get logs for function ${e}`)}}async getFunctionStatus(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/deployment/status`)).data}catch(n){throw this._handleError(n,`Failed to get status for function ${e}`)}}async generateDocumentationFromCode(e,n="node",i="function"){try{return(await this.client.post(`/v1/projects/${this.projectId}/test/documentation`,{Code:e,Runtime:n,Name:i})).data}catch(o){throw this._handleError(o,"Failed to generate documentation from code")}}async generateDocumentationForFunction(e,n){try{let i=n?{MarkdownOverride:n}:{};return(await this.client.post(`/v1/projects/${this.projectId}/functions/${e}/documentation`,i)).data}catch(i){throw this._handleError(i,`Failed to generate documentation for function ${e}`)}}async getDocumentationForFunction(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/functions/${e}/documentation`)).data}catch(n){throw this._handleError(n,`Failed to get documentation for function ${e}`)}}async streamDeployment(e,n,i){let o=p=>p.status?"status":p.progress?"progress":p.completed?"completed":p.failed||p.error?"failed":p.connected?"connected":"message",r=new URL(`v1/projects/${this.projectId}/functions/${e}/deployment/stream`,this.baseUrl).href,a={Accept:"text/event-stream","Cache-Control":"no-cache"};if(this.credentials)try{let p=await this.credentials.retrieve();if(p&&p.keyId&&p.keySecret){let d=Buffer.from(`${p.keyId}:${p.keySecret}`).toString("base64");a.Authorization=`Basic ${d}`}}catch(p){console.error("Failed to add authentication:",p)}let l=null;try{l=new AbortController;let p=await fetch(r,{method:"GET",headers:a,signal:l.signal});if(!p.ok)throw new Error(`SSE connection failed: ${p.status} ${p.statusText}`);if(!p.body)throw new Error("Response body is null");let d=p.body.getReader(),f=new TextDecoder,g="";return(async()=>{let y="";try{for(;;){let{done:v,value:$}=await d.read();if(v)break;let P=f.decode($,{stream:!0});g+=P;let D=g.split(`
3
3
  `);g=D.pop()||"";for(let C of D){if(C.startsWith("event:")){y=C.substring(6).trim();continue}if(C.startsWith("data:")){let S=C.substring(5).trim();if(S)try{let b=JSON.parse(S),I=y||o(b);n({type:I,data:b}),y=""}catch{n({type:y||"message",data:S}),y=""}}C===""&&(y="")}}}catch(v){v.name!=="AbortError"&&i&&i(v)}})(),()=>{l&&l.abort()}}catch(p){throw console.error("Failed to create SSE stream:",p),i&&i(p),p}}async checkHealth(){try{return(await this.client.get("/health")).data}catch(e){throw this._handleError(e,"Health check failed")}}async getValidToken(){if(!this.credentials)return null;try{let e=await this.credentials.getOAuthToken();if(e)return{access_token:e,token_type:"Bearer",expires_in:3600};let n=await this.credentials.getBasicAuthToken();return n?{access_token:n,token_type:"Basic",expires_in:3600}:null}catch(e){return console.error(Ue.default.yellow("Failed to get authentication token:",e.message)),null}}async authenticateOAuth(e,n){try{let i=this.oauthUrl,o=new URLSearchParams;o.append("grant_type","client_credentials");let a=(await Ot.default.post(i,o,{headers:{"Content-Type":"application/x-www-form-urlencoded",Authorization:"Basic "+Buffer.from(`${e}:${n}`).toString("base64")},timeout:this.timeout})).data;return this.credentials&&await this.credentials.storeOAuthToken(a),a}catch(i){throw this._handleError(i,"OAuth authentication failed")}}_handleError(e,n){if(Ot.default.isAxiosError(e)){let i=e;if(i.response){let o=i.response.status,r=i.response.data,a=r?.message||r?.error||i.message;throw o===401?new Error('Authentication required. Please run "sinch auth login" first.'):o===403?new Error(`Permission denied: ${a}`):o===404?new Error(`Resource not found: ${a}`):o>=500?new Error(`Server error: ${a}`):new Error(`${n}: ${a}`)}else throw i.request?(console.error("DEBUG: Axios error details:",{code:i.code,message:i.message,url:i.config?.url,baseURL:i.config?.baseURL,method:i.config?.method}),i.code==="ECONNREFUSED"?new Error(`Cannot connect to API at ${this.baseUrl}. Is the server running?`):i.code==="ETIMEDOUT"?new Error(`Request timeout after ${this.timeout}ms`):new Error(`${n}: No response from server (${i.code||"unknown error"})`)):new Error(`${n}: ${i.message}`)}else throw new Error(`${n}: ${e.message||e}`)}}});function Tt(){if(!Zt)try{Zt=require("keytar")}catch{return null}return Zt}var Gn,G,Zt,ft,J,Ft,Yn=Q(()=>{"use strict";Gn=h(require("os")),G=h(require("chalk")),Zt=null;ft="sinch-functions-cli",J=Gn.userInfo().username,Ft=class{config;keychainAvailable=null;constructor(e){this.config=e}async isKeychainAvailable(){if(this.keychainAvailable!==null)return this.keychainAvailable;if(this.config.get("keySecretPlaintext"))return this.keychainAvailable=!1,!1;try{let e=Tt();if(!e)return this.keychainAvailable=!1,!1;let n=`${J}-test-${Date.now()}`;return await e.setPassword(ft,n,"test"),await e.deletePassword(ft,n),this.keychainAvailable=!0,!0}catch{return this.keychainAvailable=!1,!1}}async setPassword(e,n){if(!await this.isKeychainAvailable())return!1;let o=Tt();return o?(await o.setPassword(ft,e,n),!0):!1}async getPassword(e){if(!await this.isKeychainAvailable())return null;let i=Tt();return i?await i.getPassword(ft,e):null}async deletePassword(e){if(!await this.isKeychainAvailable())return!1;try{let i=Tt();return i?(await i.deletePassword(ft,e),!0):!1}catch{return!0}}async store(e){let{projectId:n,keyId:i,keySecret:o,applicationKey:r,applicationSecret:a}=e,l=await this.setPassword(`${J}-keySecret`,o),p=await this.setPassword(r,a);l&&p?(this.config.set("keySecretPlaintext",null),this.config.set("applicationSecretPlaintext",null)):(console.log(G.default.yellow(`
4
4
  \u26A0\uFE0F OS keychain not available (Docker/CI environment detected)`)),console.log(G.default.yellow("\u26A0\uFE0F Storing secrets in plaintext config file")),console.log(G.default.gray("Location: ~/.sinch/config.json")),console.log(G.default.gray(`
5
5
  For better security, export as environment variables instead:`)),console.log(G.default.cyan(' export SINCH_KEY_SECRET="'+o+'"')),console.log(G.default.cyan(' export SINCH_APPLICATION_SECRET="'+a+'"')),this.config.set("keySecretPlaintext",o),this.config.set("applicationSecretPlaintext",a)),this.config.set("projectId",n),this.config.set("keyId",i),this.config.set("defaultApplicationKey",r),this.config.set("credentialsStored",!0),await this.config.save()}async storeOAuthToken(e){let{access_token:n,refresh_token:i,expires_in:o,token_type:r}=e,a=new Date(Date.now()+o*1e3).toISOString(),l=await this.setPassword(`${J}-oauth-access`,n),p=!0;i&&(p=await this.setPassword(`${J}-oauth-refresh`,i)),this.config.set("oauthTokenType",r),this.config.set("oauthExpiresAt",a),this.config.set("oauthStored",l&&p),await this.config.save()}async reAuthenticateOAuth(){try{let e=await this.retrieve();if(!e)return null;let{SinchAPI:n}=(z(),M(Xe)),o=await new n({apiUrl:this.config.get("apiUrl")||"https://api.functions.dev.sinchvoice.org",projectId:e.projectId,credentials:null}).authenticateOAuth(e.keyId,e.keySecret);return await this.storeOAuthToken(o),o.access_token}catch{return null}}async getOAuthToken(){if(!this.config.get("oauthStored"))return await this.reAuthenticateOAuth();let n=this.config.get("oauthExpiresAt");if(n&&new Date(n)<new Date){console.log(G.default.gray("Token expired, re-authenticating..."));let i=await this.reAuthenticateOAuth();return i?console.log(G.default.green("\u2713 Token renewed successfully")):console.warn(G.default.yellow("Failed to renew OAuth token. Please login again.")),i}return await this.getPassword(`${J}-oauth-access`)}async storeApplicationSecret(e,n){await this.setPassword(e,n),this.config.get("defaultApplicationKey")||(this.config.set("defaultApplicationKey",e),await this.config.save())}async retrieve(){let e=process.env.SINCH_KEY_ID,n=process.env.SINCH_KEY_SECRET,i=process.env.SINCH_APPLICATION_KEY,o=process.env.SINCH_APPLICATION_SECRET;if(e&&n&&i&&o)return{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId")||"",keyId:e,keySecret:n,applicationKey:i,applicationSecret:o};if(!this.config.get("credentialsStored"))return null;let a=this.config.get("projectId"),l=this.config.get("keyId"),p=this.config.get("defaultApplicationKey"),d=await this.getPassword(`${J}-keySecret`),f=p?await this.getPassword(p):null;return(!d||!f)&&(d=d||n||null,f=f||o||null),(!d||!f)&&(d=d||this.config.get("keySecretPlaintext"),f=f||this.config.get("applicationSecretPlaintext")),!d||!f?null:{projectId:a,keyId:l,keySecret:d,applicationKey:p,applicationSecret:f}}async getApplicationCredentials(e=null){if(e||(e=this.config.get("defaultApplicationKey")),!e)return null;let n=await this.getPassword(e);return n||(n=process.env.SINCH_APPLICATION_SECRET||null),n||(n=this.config.get("applicationSecretPlaintext")),n?{applicationKey:e,applicationSecret:n}:null}async clear(){let e=this.config.get("defaultApplicationKey");await this.deletePassword(`${J}-keySecret`),await this.deletePassword(`${J}-oauth-access`),await this.deletePassword(`${J}-oauth-refresh`),e&&await this.deletePassword(e),this.config.set("projectId",null),this.config.set("keyId",null),this.config.set("defaultApplicationKey",null),this.config.set("credentialsStored",!1),this.config.set("oauthStored",!1),this.config.set("oauthTokenType",null),this.config.set("oauthExpiresAt",null),this.config.set("keySecretPlaintext",null),this.config.set("applicationSecretPlaintext",null),await this.config.save()}async hasCredentials(){if(!!(process.env.SINCH_KEY_ID&&process.env.SINCH_KEY_SECRET&&process.env.SINCH_APPLICATION_KEY&&process.env.SINCH_APPLICATION_SECRET))return!0;if(!this.config.get("credentialsStored"))return!1;if(this.config.get("keySecretPlaintext"))return!0;let i=await this.getPassword(`${J}-keySecret`),o=this.config.get("defaultApplicationKey"),r=o?await this.getPassword(o):null;return!!(i&&r)}async hasOAuthToken(){return this.config.get("oauthStored")?!!await this.getPassword(`${J}-oauth-access`):!1}getPublicInfo(){return process.env.SINCH_KEY_ID&&process.env.SINCH_KEY_SECRET&&process.env.SINCH_APPLICATION_KEY&&process.env.SINCH_APPLICATION_SECRET?{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId"),keyId:process.env.SINCH_KEY_ID,applicationKey:process.env.SINCH_APPLICATION_KEY,hasCredentials:!0,hasOAuth:!1,oauthExpiresAt:null,source:"environment"}:{projectId:this.config.get("projectId"),keyId:this.config.get("keyId"),applicationKey:this.config.get("defaultApplicationKey"),hasCredentials:this.config.get("credentialsStored",!1),hasOAuth:this.config.get("oauthStored",!1),oauthExpiresAt:this.config.get("oauthExpiresAt"),source:"config"}}async createSinchClient(e=null){let n=await this.retrieve();if(!n)throw new Error('No credentials found. Please run "sinch auth login" first.');let i=await this.getApplicationCredentials(e),{SinchClient:o}=require("@sinch/sdk-core");return new o({applicationKey:i?.applicationKey||n.applicationKey,applicationSecret:i?.applicationSecret||n.applicationSecret,projectId:n.projectId,keyId:n.keyId,keySecret:n.keySecret,conversationRegion:"us"})}async storeBasicAuthToken(e){await this.setPassword(`${J}-basic-auth`,e)&&(this.config.set("basicAuthStored",!0),await this.config.save())}async getBasicAuthToken(){return this.config.get("basicAuthStored")?await this.getPassword(`${J}-basic-auth`):null}async clearBasicAuthToken(){await this.deletePassword(`${J}-basic-auth`),this.config.set("basicAuthStored",!1),await this.config.save()}async storeFax(e){let{projectId:n,keyId:i,keySecret:o}=e;await this.setPassword(`${J}-fax-keySecret`,o)?this.config.set("faxKeySecretPlaintext",null):(console.log(G.default.yellow(`
@@ -8,7 +8,7 @@ For better security, export as environment variable instead:`)),console.log(G.de
8
8
  `,{flag:"w"})}catch{}}writeToFile(e,n,...i){try{let r=`[${new Date().toISOString()}] ${e}: ${n} ${i.length>0?JSON.stringify(i):""}
9
9
  `;Pe.appendFileSync(this.logFile,r)}catch{}}info(e,...n){console.log(oe.default.blue("\u2139"),e,...n),this.writeToFile("INFO",e,...n)}success(e,...n){console.log(oe.default.green("\u2705"),e,...n),this.writeToFile("SUCCESS",e,...n)}warn(e,...n){console.log(oe.default.yellow("\u26A0\uFE0F "),e,...n),this.writeToFile("WARN",e,...n)}error(e,...n){console.log(oe.default.red("\u274C"),e,...n),this.writeToFile("ERROR",e,...n)}debug(e,...n){this.writeToFile("DEBUG",e,...n),(this.verbose||process.env.DEBUG)&&console.log(oe.default.gray("\u{1F41B}"),oe.default.gray(e),...n)}log(e,...n){console.log(e,...n)}title(e){console.log(oe.default.blue.bold(`
10
10
  \u{1F3AF} ${e}`))}subtitle(e){console.log(oe.default.gray(`
11
- ${e}`))}list(e,n={}){let{indent:i=" ",bullet:o="\u2022"}=n;e.forEach(r=>{console.log(`${i}${oe.default.gray(o)} ${r}`)})}calculateColumnWidths(e,n){let i=e.map(o=>o.length);return n.forEach(o=>{o.forEach((r,a)=>{i[a]=Math.max(i[a]??0,String(r).length)})}),i}table(e,n){let i=this.calculateColumnWidths(e,n),o=e.map((r,a)=>r.padEnd(i[a]??0)).join(" ");console.log(oe.default.bold(o)),console.log(oe.default.gray("-".repeat(o.length))),n.forEach(r=>{let a=r.map((l,p)=>String(l).padEnd(i[p]??0)).join(" ");console.log(a)})}newline(){console.log()}},t=new tn});var et={};ut(et,{spinner:()=>c});var Xn,ei,nn,c,E=Q(()=>{"use strict";Xn=h(require("ora")),ei=h(require("cli-spinners")),nn=class{spinner=null;spinnerType=ei.default.dots;start(e){return this.spinner=(0,Xn.default)({text:e,spinner:this.spinnerType}).start(),this}succeed(e){return this.spinner&&(this.spinner.succeed(e),this.spinner=null),this}fail(e){return this.spinner&&(this.spinner.fail(e),this.spinner=null),this}info(e){return this.spinner&&(this.spinner.info(e),this.spinner=null),this}warn(e){return this.spinner&&(this.spinner.warn(e),this.spinner=null),this}stop(){return this.spinner&&(this.spinner.stop(),this.spinner=null),this}update(e){return this.spinner&&(this.spinner.text=e),this}get isSpinning(){return this.spinner?.isSpinning??!1}get text(){return this.spinner?.text??""}set text(e){this.spinner&&(this.spinner.text=e)}},c=new nn});var oi=R((Oa,si)=>{"use strict";var B=h(require("fs-extra")),Ae=h(require("path")),X=h(require("chalk")),Me=h(require("inquirer")),ti=require("commander");k();A();E();z();var tt=require("child_process"),ni=h(require("adm-zip")),sn=h(require("keytar")),ii=new ti.Command("init");ii.description("Initialize a new Sinch Functions project").argument("[template]","Template to use (simple-ivr, customer-lookup, smart-routing)").option("--name <name>","Function name (default: template name)").option("--runtime <runtime>","Runtime to use (node, csharp)").option("--skip-install","Skip npm install for Node.js projects").option("--non-interactive","Use default values without prompting").action(async(s,e)=>{try{await u.load();let n=process.cwd(),i=new T(u.getApiConfig()),o=e.runtime;o||(e.nonInteractive?o="node":o=(await Me.default.prompt([{type:"list",name:"runtime",message:"Choose a runtime:",choices:[{name:"Node.js",value:"node"},{name:"C# (.NET)",value:"csharp"}],default:"node"}])).runtime),c.start(`Fetching available templates for ${o}...`);let r=await i.listRuntimeTemplates(o);if(c.stop(),!r.templates||r.templates.length===0)throw new Error(`No templates available for runtime '${o}'`);let a=s;if(!a)if(e.nonInteractive){let C=r.templates.filter(S=>S.name&&S.name.trim());if(C.length>0)a=C[0]?.name||"",t.info(`Using default template: ${a} (non-interactive mode)`);else throw new Error("No templates available")}else{let C=r.templates.filter(b=>b.name&&b.name.trim()).map(b=>({name:`${b.name} - ${(b.description||"No description available").substring(0,100)}`,value:b.name}));a=(await Me.default.prompt([{type:"list",name:"selectedTemplate",message:"Choose a template:",choices:C,pageSize:10}])).selectedTemplate}let l=e.name;l||(e.nonInteractive?l=a:l=(await Me.default.prompt([{type:"input",name:"name",message:"Function name:",default:a,validate:S=>!S||S.trim().length===0?"Function name is required":/^[a-z][a-z0-9-]*$/.test(S.trim())?!0:"Function name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens"}])).name.trim());let p=Ae.default.join(n,l);if(await B.default.pathExists(p)){let C=!1;if(e.nonInteractive?(C=!0,t.info(`Directory '${l}' already exists. Overwriting (non-interactive mode)...`)):C=(await Me.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${l}' already exists. Overwrite?`,default:!1}])).overwrite,!C){t.info("Initialization cancelled");return}await B.default.remove(p)}await B.default.ensureDir(p);let d=r.templates.find(C=>C.name===a);if(!d){let C=r.templates.map(S=>S.name).join(", ");throw new Error(`Template '${a}' not found. Available templates: ${C}`)}let f=["node","csharp"];if(!f.includes(o))throw new Error(`Runtime '${o}' not supported. Supported runtimes: ${f.join(", ")}`);c.start(`\u{1F680} Initializing ${l} with ${a} template (${o})...`);let g=await i.downloadTemplate(o,a);new ni.default(g).extractAllTo(p,!0),c.succeed("\u{1F4E6} Template extracted");let y={},v=[],$=Ae.default.join(p,"template.json");if(await B.default.pathExists($)){let C=await B.default.readJson($);if(C.variables&&Object.keys(C.variables).length>0)if(e.nonInteractive){t.info("\u{1F4DD} Using default values for template variables (non-interactive mode):");for(let[b,I]of Object.entries(C.variables)){let _;typeof I=="string"?_=I:_=I.default||"",y[b]=_,t.info(` ${b}: ${_}`)}}else{t.newline(),t.info("\u{1F4DD} Configure template variables:");for(let[b,I]of Object.entries(C.variables)){let _;typeof I=="string"?_={type:"input",name:b,message:`${b.replace(/_/g," ").toLowerCase()}:`,default:I}:(_={type:I.type==="number"?"number":"input",name:b,message:`${I.description||b.replace(/_/g," ").toLowerCase()}:`,default:I.default},I.type==="number"&&(_.validate=ke=>I.min!==void 0&&ke<I.min?`Value must be at least ${I.min}`:I.max!==void 0&&ke>I.max?`Value must be at most ${I.max}`:!0));let Fe=await Me.default.prompt([_]);y[b]=Fe[b]}}let S="sinch-functions-cli";if(C.secrets&&Object.keys(C.secrets).length>0)if(v=Object.keys(C.secrets),e.nonInteractive){t.info("\u{1F4DD} Template secrets detected (non-interactive mode):");for(let b of Object.keys(C.secrets))t.info(` ${b}: [will need to be set manually]`)}else{t.newline(),t.info("\u{1F510} Configure template secrets (stored securely in OS keychain):");for(let[b,I]of Object.entries(C.secrets)){let _=I.description||b.replace(/_/g," ").toLowerCase(),Fe=I.required!==!1,ke={type:"password",name:b,message:`${_}:`,validate:H=>Fe&&(!H||H.trim()==="")?"This secret is required":!0},pt=(await Me.default.prompt([ke]))[b];if(pt&&pt.trim()!=="")try{let H=`${l}-${b}`;await sn.default.setPassword(S,H,pt),t.info(` \u2705 ${b} stored securely in keychain`)}catch(H){t.warn(` \u26A0\uFE0F Could not store ${b} in keychain: ${H.message}`),t.info(` \u{1F4A1} You can add it later with: sinch secrets add ${b} <value>`)}}}await B.default.remove($)}c.start("\u{1F527} Finalizing function configuration...");let P=Ae.default.join(p,"sinch.json"),D;if(await B.default.pathExists(P)){if(D=await B.default.readJson(P),D.name=l,D.description=`Sinch Functions function: ${l}`,D.functionId=null,delete D.projectId,delete D.voiceAppId,D.variables)for(let[C,S]of Object.entries(D.variables))typeof S=="string"&&(S==="your-project-id"||S==="{{PROJECT_ID}}"?D.variables[C]=u.get("projectId"):(S==="your-application-key"||S==="{{SINCH_APPLICATION_KEY}}")&&(D.variables[C]=u.get("defaultApplicationKey")));D.created=new Date().toISOString(),D.variables={},D.secrets&&delete D.secrets}else D={name:l,functionId:null,runtime:o,description:`Sinch Functions function: ${l}`,created:new Date().toISOString(),variables:{},custom:{}};if(await B.default.writeJson(P,D,{spaces:2}),o==="node"){let C=Ae.default.join(p,"package.json");if(await B.default.pathExists(C)){let j=await B.default.readJson(C);j.name=l,j.description=D.description,await B.default.writeJson(C,j,{spaces:2})}let S=Ae.default.join(p,".env"),b=`# Sinch Functions Environment Variables
11
+ ${e}`))}list(e,n={}){let{indent:i=" ",bullet:o="\u2022"}=n;e.forEach(r=>{console.log(`${i}${oe.default.gray(o)} ${r}`)})}calculateColumnWidths(e,n){let i=e.map(o=>o.length);return n.forEach(o=>{o.forEach((r,a)=>{i[a]=Math.max(i[a]??0,String(r).length)})}),i}table(e,n){let i=this.calculateColumnWidths(e,n),o=e.map((r,a)=>r.padEnd(i[a]??0)).join(" ");console.log(oe.default.bold(o)),console.log(oe.default.gray("-".repeat(o.length))),n.forEach(r=>{let a=r.map((l,p)=>String(l).padEnd(i[p]??0)).join(" ");console.log(a)})}newline(){console.log()}},t=new tn});var et={};ut(et,{spinner:()=>c});var Xn,ei,nn,c,E=Q(()=>{"use strict";Xn=h(require("ora")),ei=h(require("cli-spinners")),nn=class{spinner=null;spinnerType=ei.default.dots;start(e){return this.spinner=(0,Xn.default)({text:e,spinner:this.spinnerType}).start(),this}succeed(e){return this.spinner&&(this.spinner.succeed(e),this.spinner=null),this}fail(e){return this.spinner&&(this.spinner.fail(e),this.spinner=null),this}info(e){return this.spinner&&(this.spinner.info(e),this.spinner=null),this}warn(e){return this.spinner&&(this.spinner.warn(e),this.spinner=null),this}stop(){return this.spinner&&(this.spinner.stop(),this.spinner=null),this}update(e){return this.spinner&&(this.spinner.text=e),this}get isSpinning(){return this.spinner?.isSpinning??!1}get text(){return this.spinner?.text??""}set text(e){this.spinner&&(this.spinner.text=e)}},c=new nn});var oi=R((Ta,si)=>{"use strict";var B=h(require("fs-extra")),Ae=h(require("path")),X=h(require("chalk")),Me=h(require("inquirer")),ti=require("commander");k();A();E();z();var tt=require("child_process"),ni=h(require("adm-zip")),sn=h(require("keytar")),ii=new ti.Command("init");ii.description("Initialize a new Sinch Functions project").argument("[template]","Template to use (simple-ivr, customer-lookup, smart-routing)").option("--name <name>","Function name (default: template name)").option("--runtime <runtime>","Runtime to use (node, csharp)").option("--skip-install","Skip npm install for Node.js projects").option("--non-interactive","Use default values without prompting").action(async(s,e)=>{try{await u.load();let n=process.cwd(),i=new T(u.getApiConfig()),o=e.runtime;o||(e.nonInteractive?o="node":o=(await Me.default.prompt([{type:"list",name:"runtime",message:"Choose a runtime:",choices:[{name:"Node.js",value:"node"},{name:"C# (.NET)",value:"csharp"}],default:"node"}])).runtime),c.start(`Fetching available templates for ${o}...`);let r=await i.listRuntimeTemplates(o);if(c.stop(),!r.templates||r.templates.length===0)throw new Error(`No templates available for runtime '${o}'`);let a=s;if(!a)if(e.nonInteractive){let C=r.templates.filter(S=>S.name&&S.name.trim());if(C.length>0)a=C[0]?.name||"",t.info(`Using default template: ${a} (non-interactive mode)`);else throw new Error("No templates available")}else{let C=r.templates.filter(b=>b.name&&b.name.trim()).map(b=>({name:`${b.name} - ${(b.description||"No description available").substring(0,100)}`,value:b.name}));a=(await Me.default.prompt([{type:"list",name:"selectedTemplate",message:"Choose a template:",choices:C,pageSize:10}])).selectedTemplate}let l=e.name;l||(e.nonInteractive?l=a:l=(await Me.default.prompt([{type:"input",name:"name",message:"Function name:",default:a,validate:S=>!S||S.trim().length===0?"Function name is required":/^[a-z][a-z0-9-]*$/.test(S.trim())?!0:"Function name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens"}])).name.trim());let p=Ae.default.join(n,l);if(await B.default.pathExists(p)){let C=!1;if(e.nonInteractive?(C=!0,t.info(`Directory '${l}' already exists. Overwriting (non-interactive mode)...`)):C=(await Me.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${l}' already exists. Overwrite?`,default:!1}])).overwrite,!C){t.info("Initialization cancelled");return}await B.default.remove(p)}await B.default.ensureDir(p);let d=r.templates.find(C=>C.name===a);if(!d){let C=r.templates.map(S=>S.name).join(", ");throw new Error(`Template '${a}' not found. Available templates: ${C}`)}let f=["node","csharp"];if(!f.includes(o))throw new Error(`Runtime '${o}' not supported. Supported runtimes: ${f.join(", ")}`);c.start(`\u{1F680} Initializing ${l} with ${a} template (${o})...`);let g=await i.downloadTemplate(o,a);new ni.default(g).extractAllTo(p,!0),c.succeed("\u{1F4E6} Template extracted");let y={},v=[],$=Ae.default.join(p,"template.json");if(await B.default.pathExists($)){let C=await B.default.readJson($);if(C.variables&&Object.keys(C.variables).length>0)if(e.nonInteractive){t.info("\u{1F4DD} Using default values for template variables (non-interactive mode):");for(let[b,I]of Object.entries(C.variables)){let _;typeof I=="string"?_=I:_=I.default||"",y[b]=_,t.info(` ${b}: ${_}`)}}else{t.newline(),t.info("\u{1F4DD} Configure template variables:");for(let[b,I]of Object.entries(C.variables)){let _;typeof I=="string"?_={type:"input",name:b,message:`${b.replace(/_/g," ").toLowerCase()}:`,default:I}:(_={type:I.type==="number"?"number":"input",name:b,message:`${I.description||b.replace(/_/g," ").toLowerCase()}:`,default:I.default},I.type==="number"&&(_.validate=ke=>I.min!==void 0&&ke<I.min?`Value must be at least ${I.min}`:I.max!==void 0&&ke>I.max?`Value must be at most ${I.max}`:!0));let Fe=await Me.default.prompt([_]);y[b]=Fe[b]}}let S="sinch-functions-cli";if(C.secrets&&Object.keys(C.secrets).length>0)if(v=Object.keys(C.secrets),e.nonInteractive){t.info("\u{1F4DD} Template secrets detected (non-interactive mode):");for(let b of Object.keys(C.secrets))t.info(` ${b}: [will need to be set manually]`)}else{t.newline(),t.info("\u{1F510} Configure template secrets (stored securely in OS keychain):");for(let[b,I]of Object.entries(C.secrets)){let _=I.description||b.replace(/_/g," ").toLowerCase(),Fe=I.required!==!1,ke={type:"password",name:b,message:`${_}:`,validate:H=>Fe&&(!H||H.trim()==="")?"This secret is required":!0},pt=(await Me.default.prompt([ke]))[b];if(pt&&pt.trim()!=="")try{let H=`${l}-${b}`;await sn.default.setPassword(S,H,pt),t.info(` \u2705 ${b} stored securely in keychain`)}catch(H){t.warn(` \u26A0\uFE0F Could not store ${b} in keychain: ${H.message}`),t.info(` \u{1F4A1} You can add it later with: sinch secrets add ${b} <value>`)}}}await B.default.remove($)}c.start("\u{1F527} Finalizing function configuration...");let P=Ae.default.join(p,"sinch.json"),D;if(await B.default.pathExists(P)){if(D=await B.default.readJson(P),D.name=l,D.description=`Sinch Functions function: ${l}`,D.functionId=null,delete D.projectId,delete D.voiceAppId,D.variables)for(let[C,S]of Object.entries(D.variables))typeof S=="string"&&(S==="your-project-id"||S==="{{PROJECT_ID}}"?D.variables[C]=u.get("projectId"):(S==="your-application-key"||S==="{{SINCH_APPLICATION_KEY}}")&&(D.variables[C]=u.get("defaultApplicationKey")));D.created=new Date().toISOString(),D.variables={},D.secrets&&delete D.secrets}else D={name:l,functionId:null,runtime:o,description:`Sinch Functions function: ${l}`,created:new Date().toISOString(),variables:{},custom:{}};if(await B.default.writeJson(P,D,{spaces:2}),o==="node"){let C=Ae.default.join(p,"package.json");if(await B.default.pathExists(C)){let j=await B.default.readJson(C);j.name=l,j.description=D.description,await B.default.writeJson(C,j,{spaces:2})}let S=Ae.default.join(p,".env"),b=`# Sinch Functions Environment Variables
12
12
  `;b+=`# Generated by sinch functions init
13
13
 
14
14
  `,b+=`# Template Variables
@@ -32,12 +32,12 @@ ${e}`))}list(e,n={}){let{indent:i=" ",bullet:o="\u2022"}=n;e.forEach(r=>{consol
32
32
  `,b+=`NODE_ENV=development
33
33
  `,b+=`PORT=3000
34
34
  `,b+=`SINCH_TUNNEL=false
35
- `,await B.default.writeFile(S,b),t.info(""),t.info("\u{1F510} Secrets Management for Node.js:");try{let j=await u.getCredentials();j&&j.keySecret?(t.info(" \u2705 Sinch credentials found in secure storage"),t.info(" \u2705 F5 debugging will automatically load secrets from OS keychain"),t.info(""),t.info(" \u{1F4A1} To add custom secrets, use:"),t.info(` ${X.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`)):(t.info(" \u26A0\uFE0F No Sinch credentials found in secure storage"),t.info(""),t.info(" To set up authentication:"),t.info(` ${X.default.cyan("sinch auth login")}`),t.info(""),t.info(" To add custom secrets:"),t.info(` ${X.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`))}catch{t.info(" \u2139\uFE0F Set up authentication with:"),t.info(` ${X.default.cyan("sinch auth login")}`)}t.info(""),t.info(" \u{1F4DD} Note: Secrets are stored securely in your OS keychain"),t.info(" \u{1F4DD} Note: F5 debugging requires keytar (npm install keytar)")}if(o==="csharp"){let C=Ae.default.join(p,"appsettings.json"),S;await B.default.pathExists(C)?S=await B.default.readJson(C):S={Logging:{LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}},AllowedHosts:"*"},S.Logging||(S.Logging={LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}}),S.AllowedHosts||(S.AllowedHosts="*"),Object.keys(y).forEach(j=>{S[j]=y[j]});let b=u.get("projectId"),I=u.get("defaultApplicationKey"),_=u.get("keyId");S.PROJECT_ID=b||"",S.PROJECT_ID_API_KEY=_||"",S.PROJECT_ID_API_SECRET="",S.VOICE_APPLICATION_KEY=I||"",S.VOICE_APPLICATION_SECRET="",v.forEach(j=>{S[j]=""}),await B.default.writeJson(C,S,{spaces:2});let Fe=Ae.default.join(p,"appsettings.Development.json"),ke={Logging:{LogLevel:{Default:"Debug","Microsoft.AspNetCore":"Information"}},SinchTunnel:!1};await B.default.writeJson(Fe,ke,{spaces:2});try{let j=await u.getCredentials();await new Promise((H,ae)=>{let ce=(0,tt.spawn)("dotnet",["user-secrets","init"],{cwd:p,shell:!0});ce.on("close",Le=>Le===0?H():ae(new Error("Failed to init user-secrets"))),ce.on("error",ae)}),j&&j.keySecret&&await new Promise((H,ae)=>{let ce=(0,tt.spawn)("dotnet",["user-secrets","set","PROJECT_ID_API_SECRET",j.keySecret],{cwd:p,shell:!0});ce.on("close",Le=>Le===0?H():ae(new Error("Failed to set API secret"))),ce.on("error",ae)}),j&&j.applicationSecret&&await new Promise((H,ae)=>{let ce=(0,tt.spawn)("dotnet",["user-secrets","set","VOICE_APPLICATION_SECRET",j.applicationSecret],{cwd:p,shell:!0});ce.on("close",Le=>Le===0?H():ae(new Error("Failed to set app secret"))),ce.on("error",ae)});let pt="sinch-functions-cli";for(let H of v)try{let ae=`${l}-${H}`,ce=await sn.default.getPassword(pt,ae);ce&&await new Promise((Le,Bn)=>{let Kn=(0,tt.spawn)("dotnet",["user-secrets","set",H,ce],{cwd:p,shell:!0});Kn.on("close",ko=>ko===0?Le():Bn(new Error(`Failed to set ${H}`))),Kn.on("error",Bn)})}catch{}(j&&(j.keySecret||j.applicationSecret)||v.length>0)&&(t.info(""),t.info("\u{1F510} Secrets Management for C#:"),t.info(" \u2705 User secrets have been configured automatically"),t.info(" You can view them with: "+X.default.cyan("dotnet user-secrets list")),v.length>0&&t.info(" \u{1F4A1} Template secrets have been added to user-secrets"))}catch{t.info(""),t.info("\u{1F510} Secrets Management for C#:"),t.info(" For local development, use dotnet user-secrets:"),t.info(` ${X.default.cyan("dotnet user-secrets init")}`),t.info(` ${X.default.cyan('dotnet user-secrets set "PROJECT_ID_API_SECRET" "your-api-secret"')}`),t.info(` ${X.default.cyan('dotnet user-secrets set "VOICE_APPLICATION_SECRET" "your-app-secret"')}`)}}if(c.succeed("\u{1F680} Function initialized successfully"),t.newline(),t.title(`Function: ${X.default.cyan(l)}`),t.info(`Template: ${X.default.yellow(a)}`),t.info(`Runtime: ${X.default.blue(o)}`),t.info(`Location: ${X.default.gray(p)}`),o==="node"&&!e.skipInstall){t.newline(),c.start("Installing npm packages...");try{await new Promise((C,S)=>{let b=(0,tt.spawn)("npm",["install"],{cwd:p,stdio:"inherit",shell:!0});b.on("close",I=>{I===0?C():S(new Error(`npm install failed with code ${I}`))}),b.on("error",I=>{S(I)})}),c.succeed("\u{1F4E6} Dependencies installed successfully")}catch(C){c.fail("\u{1F4E6} Failed to install dependencies"),C.code==="ENOENT"?t.warn("npm not found. Please ensure Node.js is installed and in your PATH."):t.debug(`npm install error: ${C.message}`)}}t.newline(),t.info("\u{1F4CB} Next steps:"),t.info(` 1. \u{1F4C1} Navigate to function: ${X.default.cyan(`cd ${l}`)}`),o==="node"?t.info(" 2. \u{1F3C3} Start development: sinch functions dev"):t.info(" 2. \u{1F3C3} Start development: dotnet run"),t.info(" 3. \u{1F680} Deploy to production: sinch functions deploy"),t.info(" 4. \u{1F4CA} View logs: sinch functions logs --follow"),t.newline(),t.info("\u{1F4A1} Template info:"),t.info(`\u2022 ${d.description}`),d.features&&d.features.length>0&&d.features.forEach(C=>{t.info(`\u2022 ${C}`)})}catch(n){c.stop(),t.error(`Failed to initialize function: ${n.message}`),process.exit(1)}});si.exports=ii});var di=R((Ua,li)=>{"use strict";var N=h(require("chalk")),ri=require("commander"),ai=h(require("cli-table3")),mt=h(require("inquirer"));z();k();A();E();var ci=new ri.Command("list");ci.description("List all functions").option("--status <status>","Filter by status (Running, Failed, Pending, Building)").option("--runtime <runtime>","Filter by runtime (node, csharp, python)").option("--limit <limit>","Limit number of results","50").option("-i, --interactive","Interactive mode - select function for actions").action(async s=>{try{await u.load();let e=new T(u.getApiConfig());c.start("\u{1F4CB} Loading functions...");let n={limit:parseInt(s.limit||"50")};s.status&&(n.status=s.status),s.runtime&&(n.runtime=s.runtime);let i=await e.listFunctions();if(c.succeed(`\u{1F4CB} Found ${i.functions.length} functions`),i.functions.length===0){t.newline(),t.info("No functions found"),t.info("\u{1F4A1} Create your first function with:"),t.info(` ${N.default.cyan("sinch functions init")}`);return}t.newline(),t.title("Functions:");let o=i.functions.map(a=>{let l=new Date(a.createdAt).toLocaleDateString(),p=on(a.status),d=a.containerAppUrl?a.containerAppUrl.length>40?a.containerAppUrl.substring(0,37)+"...":a.containerAppUrl:N.default.gray("Not deployed");return[N.default.cyan(a.name),N.default.yellow(a.runtime),p,N.default.gray(l),N.default.blue(d)]}),r=new ai.default({head:["Name","Runtime","Status","Created","URL"],style:{head:["cyan"]},colWidths:[20,10,15,12,45]});if(r.push(...o),console.log(r.toString()),i.pagination){let{page:a,totalCount:l,totalPages:p}=i.pagination;t.newline(),t.info(N.default.gray(`Page ${a} of ${p} (${l} total functions)`)),a<p&&t.info(N.default.gray("\u{1F4A1} Use --limit to see more results"))}if(s.interactive&&i.functions.length>0){t.newline();let a=i.functions.map(d=>({name:`${d.name.padEnd(20)} ${d.runtime.padEnd(8)} ${on(d.status).padEnd(20)} ${d.id.substring(0,8)}`,value:d.id,short:d.name}));a.push(new mt.default.Separator),a.push({name:N.default.gray("Exit"),value:"exit",short:"Exit"});let{selectedFunction:l}=await mt.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function for actions:",choices:a,pageSize:15}]);if(l==="exit")return;let p=i.functions.find(d=>d.id===l);p&&await Bo(p,e)}else t.newline(),t.info("\u{1F4A1} Function commands:"),t.info(` \u2022 View details: ${N.default.cyan("sinch functions status 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 View logs: ${N.default.cyan("sinch functions logs 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Download: ${N.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Interactive mode: ${N.default.cyan("sinch functions list -i")}`),t.info(` \u2022 Deploy new function: ${N.default.cyan("sinch functions deploy")}`)}catch(e){c.stop(),t.error(`Failed to list functions: ${e.message}`),process.exit(1)}});function on(s){return{Running:N.default.green("\u2705 Running"),Failed:N.default.red("\u274C Failed"),Pending:N.default.yellow("\u23F3 Pending"),Building:N.default.blue("\u{1F528} Building")}[s]||N.default.gray(s)}async function Bo(s,e){t.newline(),t.info(`\u{1F4CB} Selected: ${N.default.cyan(s.name)}`),t.info(` ID: ${N.default.gray(s.id)}`),t.info(` Status: ${on(s.status)}`),t.newline();let{action:n}=await mt.default.prompt([{type:"list",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F4E5} Download source code",value:"download"},{name:"\u{1F4CA} View status details",value:"status"},{name:"\u{1F4DC} View logs",value:"logs"},{name:"\u{1F517} Copy URL to clipboard",value:"copy-url"},{name:"\u{1F5D1}\uFE0F Delete function",value:"delete"},new mt.default.Separator,{name:N.default.gray("Back"),value:"back"}]}]);switch(n){case"download":t.info(`
35
+ `,await B.default.writeFile(S,b),t.info(""),t.info("\u{1F510} Secrets Management for Node.js:");try{let j=await u.getCredentials();j&&j.keySecret?(t.info(" \u2705 Sinch credentials found in secure storage"),t.info(" \u2705 F5 debugging will automatically load secrets from OS keychain"),t.info(""),t.info(" \u{1F4A1} To add custom secrets, use:"),t.info(` ${X.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`)):(t.info(" \u26A0\uFE0F No Sinch credentials found in secure storage"),t.info(""),t.info(" To set up authentication:"),t.info(` ${X.default.cyan("sinch auth login")}`),t.info(""),t.info(" To add custom secrets:"),t.info(` ${X.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`))}catch{t.info(" \u2139\uFE0F Set up authentication with:"),t.info(` ${X.default.cyan("sinch auth login")}`)}t.info(""),t.info(" \u{1F4DD} Note: Secrets are stored securely in your OS keychain"),t.info(" \u{1F4DD} Note: F5 debugging requires keytar (npm install keytar)")}if(o==="csharp"){let C=Ae.default.join(p,"appsettings.json"),S;await B.default.pathExists(C)?S=await B.default.readJson(C):S={Logging:{LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}},AllowedHosts:"*"},S.Logging||(S.Logging={LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}}),S.AllowedHosts||(S.AllowedHosts="*"),Object.keys(y).forEach(j=>{S[j]=y[j]});let b=u.get("projectId"),I=u.get("defaultApplicationKey"),_=u.get("keyId");S.PROJECT_ID=b||"",S.PROJECT_ID_API_KEY=_||"",S.PROJECT_ID_API_SECRET="",S.VOICE_APPLICATION_KEY=I||"",S.VOICE_APPLICATION_SECRET="",v.forEach(j=>{S[j]=""}),await B.default.writeJson(C,S,{spaces:2});let Fe=Ae.default.join(p,"appsettings.Development.json"),ke={Logging:{LogLevel:{Default:"Debug","Microsoft.AspNetCore":"Information"}},SinchTunnel:!1};await B.default.writeJson(Fe,ke,{spaces:2});try{let j=await u.getCredentials();await new Promise((H,ae)=>{let ce=(0,tt.spawn)("dotnet",["user-secrets","init"],{cwd:p,shell:!0});ce.on("close",Le=>Le===0?H():ae(new Error("Failed to init user-secrets"))),ce.on("error",ae)}),j&&j.keySecret&&await new Promise((H,ae)=>{let ce=(0,tt.spawn)("dotnet",["user-secrets","set","PROJECT_ID_API_SECRET",j.keySecret],{cwd:p,shell:!0});ce.on("close",Le=>Le===0?H():ae(new Error("Failed to set API secret"))),ce.on("error",ae)}),j&&j.applicationSecret&&await new Promise((H,ae)=>{let ce=(0,tt.spawn)("dotnet",["user-secrets","set","VOICE_APPLICATION_SECRET",j.applicationSecret],{cwd:p,shell:!0});ce.on("close",Le=>Le===0?H():ae(new Error("Failed to set app secret"))),ce.on("error",ae)});let pt="sinch-functions-cli";for(let H of v)try{let ae=`${l}-${H}`,ce=await sn.default.getPassword(pt,ae);ce&&await new Promise((Le,Bn)=>{let Kn=(0,tt.spawn)("dotnet",["user-secrets","set",H,ce],{cwd:p,shell:!0});Kn.on("close",Po=>Po===0?Le():Bn(new Error(`Failed to set ${H}`))),Kn.on("error",Bn)})}catch{}(j&&(j.keySecret||j.applicationSecret)||v.length>0)&&(t.info(""),t.info("\u{1F510} Secrets Management for C#:"),t.info(" \u2705 User secrets have been configured automatically"),t.info(" You can view them with: "+X.default.cyan("dotnet user-secrets list")),v.length>0&&t.info(" \u{1F4A1} Template secrets have been added to user-secrets"))}catch{t.info(""),t.info("\u{1F510} Secrets Management for C#:"),t.info(" For local development, use dotnet user-secrets:"),t.info(` ${X.default.cyan("dotnet user-secrets init")}`),t.info(` ${X.default.cyan('dotnet user-secrets set "PROJECT_ID_API_SECRET" "your-api-secret"')}`),t.info(` ${X.default.cyan('dotnet user-secrets set "VOICE_APPLICATION_SECRET" "your-app-secret"')}`)}}if(c.succeed("\u{1F680} Function initialized successfully"),t.newline(),t.title(`Function: ${X.default.cyan(l)}`),t.info(`Template: ${X.default.yellow(a)}`),t.info(`Runtime: ${X.default.blue(o)}`),t.info(`Location: ${X.default.gray(p)}`),o==="node"&&!e.skipInstall){t.newline(),c.start("Installing npm packages...");try{await new Promise((C,S)=>{let b=(0,tt.spawn)("npm",["install"],{cwd:p,stdio:"inherit",shell:!0});b.on("close",I=>{I===0?C():S(new Error(`npm install failed with code ${I}`))}),b.on("error",I=>{S(I)})}),c.succeed("\u{1F4E6} Dependencies installed successfully")}catch(C){c.fail("\u{1F4E6} Failed to install dependencies"),C.code==="ENOENT"?t.warn("npm not found. Please ensure Node.js is installed and in your PATH."):t.debug(`npm install error: ${C.message}`)}}t.newline(),t.info("\u{1F4CB} Next steps:"),t.info(` 1. \u{1F4C1} Navigate to function: ${X.default.cyan(`cd ${l}`)}`),o==="node"?t.info(" 2. \u{1F3C3} Start development: sinch functions dev"):t.info(" 2. \u{1F3C3} Start development: dotnet run"),t.info(" 3. \u{1F680} Deploy to production: sinch functions deploy"),t.info(" 4. \u{1F4CA} View logs: sinch functions logs --follow"),t.newline(),t.info("\u{1F4A1} Template info:"),t.info(`\u2022 ${d.description}`),d.features&&d.features.length>0&&d.features.forEach(C=>{t.info(`\u2022 ${C}`)})}catch(n){c.stop(),t.error(`Failed to initialize function: ${n.message}`),process.exit(1)}});si.exports=ii});var di=R((qa,li)=>{"use strict";var N=h(require("chalk")),ri=require("commander"),ai=h(require("cli-table3")),mt=h(require("inquirer"));z();k();A();E();var ci=new ri.Command("list");ci.description("List all functions").option("--status <status>","Filter by status (Running, Failed, Pending, Building)").option("--runtime <runtime>","Filter by runtime (node, csharp, python)").option("--limit <limit>","Limit number of results","50").option("-i, --interactive","Interactive mode - select function for actions").action(async s=>{try{await u.load();let e=new T(u.getApiConfig());c.start("\u{1F4CB} Loading functions...");let n={limit:parseInt(s.limit||"50")};s.status&&(n.status=s.status),s.runtime&&(n.runtime=s.runtime);let i=await e.listFunctions();if(c.succeed(`\u{1F4CB} Found ${i.functions.length} functions`),i.functions.length===0){t.newline(),t.info("No functions found"),t.info("\u{1F4A1} Create your first function with:"),t.info(` ${N.default.cyan("sinch functions init")}`);return}t.newline(),t.title("Functions:");let o=i.functions.map(a=>{let l=new Date(a.createdAt).toLocaleDateString(),p=on(a.status),d=a.containerAppUrl?a.containerAppUrl.length>40?a.containerAppUrl.substring(0,37)+"...":a.containerAppUrl:N.default.gray("Not deployed");return[N.default.cyan(a.name),N.default.yellow(a.runtime),p,N.default.gray(l),N.default.blue(d)]}),r=new ai.default({head:["Name","Runtime","Status","Created","URL"],style:{head:["cyan"]},colWidths:[20,10,15,12,45]});if(r.push(...o),console.log(r.toString()),i.pagination){let{page:a,totalCount:l,totalPages:p}=i.pagination;t.newline(),t.info(N.default.gray(`Page ${a} of ${p} (${l} total functions)`)),a<p&&t.info(N.default.gray("\u{1F4A1} Use --limit to see more results"))}if(s.interactive&&i.functions.length>0){t.newline();let a=i.functions.map(d=>({name:`${d.name.padEnd(20)} ${d.runtime.padEnd(8)} ${on(d.status).padEnd(20)} ${d.id.substring(0,8)}`,value:d.id,short:d.name}));a.push(new mt.default.Separator),a.push({name:N.default.gray("Exit"),value:"exit",short:"Exit"});let{selectedFunction:l}=await mt.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function for actions:",choices:a,pageSize:15}]);if(l==="exit")return;let p=i.functions.find(d=>d.id===l);p&&await Ko(p,e)}else t.newline(),t.info("\u{1F4A1} Function commands:"),t.info(` \u2022 View details: ${N.default.cyan("sinch functions status 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 View logs: ${N.default.cyan("sinch functions logs 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Download: ${N.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Interactive mode: ${N.default.cyan("sinch functions list -i")}`),t.info(` \u2022 Deploy new function: ${N.default.cyan("sinch functions deploy")}`)}catch(e){c.stop(),t.error(`Failed to list functions: ${e.message}`),process.exit(1)}});function on(s){return{Running:N.default.green("\u2705 Running"),Failed:N.default.red("\u274C Failed"),Pending:N.default.yellow("\u23F3 Pending"),Building:N.default.blue("\u{1F528} Building")}[s]||N.default.gray(s)}async function Ko(s,e){t.newline(),t.info(`\u{1F4CB} Selected: ${N.default.cyan(s.name)}`),t.info(` ID: ${N.default.gray(s.id)}`),t.info(` Status: ${on(s.status)}`),t.newline();let{action:n}=await mt.default.prompt([{type:"list",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F4E5} Download source code",value:"download"},{name:"\u{1F4CA} View status details",value:"status"},{name:"\u{1F4DC} View logs",value:"logs"},{name:"\u{1F517} Copy URL to clipboard",value:"copy-url"},{name:"\u{1F5D1}\uFE0F Delete function",value:"delete"},new mt.default.Separator,{name:N.default.gray("Back"),value:"back"}]}]);switch(n){case"download":t.info(`
36
36
  \u{1F4A1} To download this function, run:`),t.info(` ${N.default.cyan(`sinch functions download ${s.id}`)}`);break;case"status":t.info(`
37
37
  \u{1F4A1} To view status, run:`),t.info(` ${N.default.cyan(`sinch functions status ${s.id}`)}`);break;case"logs":t.info(`
38
38
  \u{1F4A1} To view logs, run:`),t.info(` ${N.default.cyan(`sinch functions logs ${s.id}`)}`);break;case"copy-url":s.containerAppUrl?(await require("clipboardy").write(s.containerAppUrl),t.success(`\u2705 URL copied to clipboard: ${s.containerAppUrl}`)):t.warn("\u26A0\uFE0F Function has no URL (not deployed)");break;case"delete":t.info(`
39
- \u{1F4A1} To delete this function, run:`),t.info(` ${N.default.cyan(`sinch functions delete ${s.id}`)}`);break;case"back":return}}li.exports=ci});async function an(s){if(!await u.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let e=await u.getApplicationCredentials();if(!e)throw new Error('No application credentials found. Run "sinch auth login" first.');let i=`https://callingapi.sinch.com/v1/configuration/callbacks/applications/${e.applicationKey}/`,o={url:{primary:s}},r=`${e.applicationKey}:${e.applicationSecret}`,a=Buffer.from(r).toString("base64");await rn.default.post(i,o,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/json"},timeout:1e4}),await new Promise(f=>setTimeout(f,1e3));let d=(await rn.default.get(i,{headers:{Authorization:`Basic ${a}`},timeout:1e4})).data?.url?.primary;if(d!==s)throw t.debug(`Callback verification mismatch. Expected: ${s}, Got: ${d}`),new Error(`Callback URL update verification failed. Expected: ${s}, Got: ${d}`);t.debug("Voice callback URL successfully updated and verified")}var rn,pi=Q(()=>{"use strict";rn=h(require("axios"));k();A()});function Ko(){return"https://us.conversation.api.sinch.com"}async function Vo(s,e,n){let i="https://auth.sinch.com/oauth2/token",o=new URLSearchParams;o.append("grant_type","client_credentials");let r=`${e}:${n}`,a=Buffer.from(r).toString("base64");return(await ht.default.post(i,o,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/x-www-form-urlencoded"},timeout:1e4})).data.access_token}async function Lt(){let s=yt.default.join(process.cwd(),"appsettings.json");if(await we.default.pathExists(s))try{let n=await we.default.readJson(s);if(n.Webhooks?.AutoConfigureConversation!==!0)return{isConversation:!1};let i=n.CONVERSATION_APP_ID;if(i)return{isConversation:!0,appId:i}}catch(n){t.debug("Could not read appsettings.json: "+n.message)}let e=yt.default.join(process.cwd(),".env");if(await we.default.pathExists(e))try{let n=await we.default.readFile(e,"utf8"),i={};if(n.split(`
40
- `).forEach(r=>{if(r.trim()&&!r.trim().startsWith("#")){let[a,...l]=r.split("=");a&&(i[a.trim()]=l.join("=").trim())}}),i.AUTO_CONFIGURE_CONVERSATION!=="true")return{isConversation:!1};let o=i.CONVERSATION_APP_ID;if(o)return{isConversation:!0,appId:o}}catch(n){t.debug("Could not read .env file: "+n.message)}return{isConversation:!1}}async function cn(s){if(!await u.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let{isConversation:e,appId:n}=await Lt();if(t.debug(`isConversationFunction check: isConversation=${e}, appId=${n}`),!e||!n){t.debug("Not a Conversation function or missing CONVERSATION_APP_ID, skipping webhook config");return}let i=await u.getCredentials();if(!i?.projectId||!i?.keyId||!i?.keySecret)throw new Error('Missing project credentials. Run "sinch auth login" first.');let o=Ko(),r=`${s}/conversation`;t.debug(`Conversation webhook URL: ${r}`),t.debug(`Project ID: ${i.projectId}, App ID: ${n}`),t.debug("Getting OAuth access token...");let a=await Vo(i.projectId,i.keyId,i.keySecret);t.debug("Got access token successfully");let l={Authorization:`Bearer ${a}`,"Content-Type":"application/json"},p=`${o}/v1/projects/${i.projectId}/apps/${n}/webhooks`;t.debug(`Listing webhooks: GET ${p}`);let d=await ht.default.get(p,{headers:l,timeout:1e4});t.debug(`Found ${d.data.webhooks?.length||0} webhooks`);let f=d.data.webhooks?.find(v=>v.target?.includes(".sinch.com")&&(v.target?.includes("fn-dev.")||v.target?.includes("fn-prod.")||v.target?.includes("functions."))),g=["MESSAGE_INBOUND"];if(f){t.debug(`Found existing webhook: id=${f.id}, target=${f.target}`);let v=`${o}/v1/projects/${i.projectId}/webhooks/${f.id}`;t.debug(`Deleting webhook: DELETE ${v}`);try{await ht.default.delete(v,{headers:l,timeout:1e4}),t.debug(`Deleted existing Conversation webhook ${f.id}`)}catch($){t.debug(`Failed to delete webhook: ${$.response?.status} ${$.response?.data?JSON.stringify($.response.data):$.message}`)}}let w=`${o}/v1/projects/${i.projectId}/webhooks`,y={app_id:n,target:r,target_type:"HTTP",triggers:g};t.debug(`Creating webhook: POST ${w}`),t.debug(`Payload: ${JSON.stringify(y)}`);try{let v=await ht.default.post(w,y,{headers:l,timeout:1e4});t.debug(`Created new Conversation webhook: ${JSON.stringify(v.data)}`)}catch(v){throw t.debug(`Failed to create webhook: ${v.response?.status} ${v.response?.data?JSON.stringify(v.response.data):v.message}`),v}t.debug("Conversation webhook successfully configured")}async function ln(){let s=yt.default.join(process.cwd(),"appsettings.json");if(await we.default.pathExists(s))try{let n=await we.default.readJson(s);return n.Webhooks?n.Webhooks.AutoConfigureVoice===!0:!0}catch(n){t.debug("Could not read appsettings.json: "+n.message)}let e=yt.default.join(process.cwd(),".env");if(await we.default.pathExists(e))try{let n=await we.default.readFile(e,"utf8"),i={};return n.split(`
39
+ \u{1F4A1} To delete this function, run:`),t.info(` ${N.default.cyan(`sinch functions delete ${s.id}`)}`);break;case"back":return}}li.exports=ci});async function an(s){if(!await u.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let e=await u.getApplicationCredentials();if(!e)throw new Error('No application credentials found. Run "sinch auth login" first.');let i=`https://callingapi.sinch.com/v1/configuration/callbacks/applications/${e.applicationKey}/`,o={url:{primary:s}},r=`${e.applicationKey}:${e.applicationSecret}`,a=Buffer.from(r).toString("base64");await rn.default.post(i,o,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/json"},timeout:1e4}),await new Promise(f=>setTimeout(f,1e3));let d=(await rn.default.get(i,{headers:{Authorization:`Basic ${a}`},timeout:1e4})).data?.url?.primary;if(d!==s)throw t.debug(`Callback verification mismatch. Expected: ${s}, Got: ${d}`),new Error(`Callback URL update verification failed. Expected: ${s}, Got: ${d}`);t.debug("Voice callback URL successfully updated and verified")}var rn,pi=Q(()=>{"use strict";rn=h(require("axios"));k();A()});function Vo(){return"https://us.conversation.api.sinch.com"}async function Ho(s,e,n){let i="https://auth.sinch.com/oauth2/token",o=new URLSearchParams;o.append("grant_type","client_credentials");let r=`${e}:${n}`,a=Buffer.from(r).toString("base64");return(await ht.default.post(i,o,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/x-www-form-urlencoded"},timeout:1e4})).data.access_token}async function Lt(){let s=yt.default.join(process.cwd(),"appsettings.json");if(await we.default.pathExists(s))try{let n=await we.default.readJson(s);if(n.Webhooks?.AutoConfigureConversation!==!0)return{isConversation:!1};let i=n.CONVERSATION_APP_ID;if(i)return{isConversation:!0,appId:i}}catch(n){t.debug("Could not read appsettings.json: "+n.message)}let e=yt.default.join(process.cwd(),".env");if(await we.default.pathExists(e))try{let n=await we.default.readFile(e,"utf8"),i={};if(n.split(`
40
+ `).forEach(r=>{if(r.trim()&&!r.trim().startsWith("#")){let[a,...l]=r.split("=");a&&(i[a.trim()]=l.join("=").trim())}}),i.AUTO_CONFIGURE_CONVERSATION!=="true")return{isConversation:!1};let o=i.CONVERSATION_APP_ID;if(o)return{isConversation:!0,appId:o}}catch(n){t.debug("Could not read .env file: "+n.message)}return{isConversation:!1}}async function cn(s){if(!await u.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let{isConversation:e,appId:n}=await Lt();if(t.debug(`isConversationFunction check: isConversation=${e}, appId=${n}`),!e||!n){t.debug("Not a Conversation function or missing CONVERSATION_APP_ID, skipping webhook config");return}let i=await u.getCredentials();if(!i?.projectId||!i?.keyId||!i?.keySecret)throw new Error('Missing project credentials. Run "sinch auth login" first.');let o=Vo(),r=`${s}/conversation`;t.debug(`Conversation webhook URL: ${r}`),t.debug(`Project ID: ${i.projectId}, App ID: ${n}`),t.debug("Getting OAuth access token...");let a=await Ho(i.projectId,i.keyId,i.keySecret);t.debug("Got access token successfully");let l={Authorization:`Bearer ${a}`,"Content-Type":"application/json"},p=`${o}/v1/projects/${i.projectId}/apps/${n}/webhooks`;t.debug(`Listing webhooks: GET ${p}`);let d=await ht.default.get(p,{headers:l,timeout:1e4});t.debug(`Found ${d.data.webhooks?.length||0} webhooks`);let f=d.data.webhooks?.find(v=>v.target?.includes(".sinch.com")&&(v.target?.includes("fn-dev.")||v.target?.includes("fn-prod.")||v.target?.includes("functions."))),g=["MESSAGE_INBOUND"];if(f){t.debug(`Found existing webhook: id=${f.id}, target=${f.target}`);let v=`${o}/v1/projects/${i.projectId}/webhooks/${f.id}`;t.debug(`Deleting webhook: DELETE ${v}`);try{await ht.default.delete(v,{headers:l,timeout:1e4}),t.debug(`Deleted existing Conversation webhook ${f.id}`)}catch($){t.debug(`Failed to delete webhook: ${$.response?.status} ${$.response?.data?JSON.stringify($.response.data):$.message}`)}}let w=`${o}/v1/projects/${i.projectId}/webhooks`,y={app_id:n,target:r,target_type:"HTTP",triggers:g};t.debug(`Creating webhook: POST ${w}`),t.debug(`Payload: ${JSON.stringify(y)}`);try{let v=await ht.default.post(w,y,{headers:l,timeout:1e4});t.debug(`Created new Conversation webhook: ${JSON.stringify(v.data)}`)}catch(v){throw t.debug(`Failed to create webhook: ${v.response?.status} ${v.response?.data?JSON.stringify(v.response.data):v.message}`),v}t.debug("Conversation webhook successfully configured")}async function ln(){let s=yt.default.join(process.cwd(),"appsettings.json");if(await we.default.pathExists(s))try{let n=await we.default.readJson(s);return n.Webhooks?n.Webhooks.AutoConfigureVoice===!0:!0}catch(n){t.debug("Could not read appsettings.json: "+n.message)}let e=yt.default.join(process.cwd(),".env");if(await we.default.pathExists(e))try{let n=await we.default.readFile(e,"utf8"),i={};return n.split(`
41
41
  `).forEach(r=>{if(r.trim()&&!r.trim().startsWith("#")){let[a,...l]=r.split("=");a&&(i[a.trim()]=l.join("=").trim())}}),Object.keys(i).some(r=>r.startsWith("AUTO_CONFIGURE_"))?i.AUTO_CONFIGURE_VOICE==="true":!0}catch(n){t.debug("Could not read .env file: "+n.message)}return!0}var ht,we,yt,ui=Q(()=>{"use strict";ht=h(require("axios")),we=h(require("fs-extra")),yt=h(require("path"));k();A()});var hi={};ut(hi,{combineDocumentation:()=>gi,detectRuntimeFromFile:()=>mi,findFunctionFile:()=>fi,generateDocsFromLocal:()=>dn,saveDocumentationToFile:()=>pn});async function dn(){let s=process.cwd(),e=await fi(s);if(!e)throw new Error("No function file found. Make sure you're in a function directory with function.js, function.ts, index.js, index.ts, handler.js, or handler.ts");let n=await nt.readFile(e,"utf8"),i=mi(e),o=Ee.basename(s),a=await new T(u.getApiConfig()).generateDocumentationFromCode(n,i,o);return gi(a)}async function fi(s){let e=["function.js","function.ts","index.js","index.ts","handler.js","handler.ts","function.py","handler.py","Function.cs","Handler.cs"];for(let n of e){let i=Ee.join(s,n);if(await nt.pathExists(i))return i}return null}function gi(s){let e=s.documentation||"",n=s.diagram||s.callFlowDiagram;return n&&(e&&!e.endsWith(`
42
42
 
43
43
  `)&&(e+=`
@@ -48,52 +48,52 @@ ${e}`))}list(e,n={}){let{indent:i=" ",bullet:o="\u2022"}=n;e.forEach(r=>{consol
48
48
  ---
49
49
 
50
50
  `,e+=`*Documentation generated on ${new Date(s.generatedAt).toLocaleString()} using Sinch AI*
51
- `),e}async function pn(s,e){let n=Ee.resolve(e);await nt.writeFile(n,s,"utf8")}function mi(s){switch(Ee.extname(s).toLowerCase()){case".js":case".ts":return"node";case".py":return"python";case".cs":return"csharp";default:return"node"}}var nt,Ee,un=Q(()=>{"use strict";nt=h(require("fs-extra")),Ee=h(require("path"));z();k()});var Ii=R((tc,$i)=>{"use strict";var le=h(require("fs-extra")),Je=h(require("path")),x=h(require("chalk")),wi=require("commander");z();k();A();E();pi();ui();var Ci=h(require("adm-zip")),bi=h(require("os")),fn=h(require("inquirer")),wt=require("child_process"),Si=h(require("keytar")),vi=new wi.Command("deploy");vi.description("Deploy function to production").option("-n, --name <name>","Function name (default: current directory)").option("--no-wait","Don't wait for deployment to complete").option("--non-interactive","Use default values without prompting (auto-generates docs)").option("--no-docs","no doc generation").option("--private","Deploy to private namespace (internal access only, not publicly accessible)").action(async s=>{try{if(await u.load(),!u.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=u.getProjectConfig(),n=s.name||e.name,i=e.runtime;if(await Go(e,s),i==="csharp"){let f=await le.default.readdir(process.cwd()).then(w=>w.filter(y=>y.endsWith(".csproj")));if(f.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");let g=f[0];await Qo(process.cwd(),g)}c.start("\u{1F4E6} Packaging function...");let o=await Ho(n);c.succeed("\u{1F4E6} Function packaged"),c.start("\u{1F527} Preparing configuration...");let r=await zo(i,n);c.succeed("\u{1F527} Configuration prepared");let a=await Zo(e,s);c.start("\u{1F680} Submitting deployment...");let l=new T(u.getApiConfig()),p=await le.default.readFile(o),d=await l.deployFunction(n,i,p,r,a);if(await le.default.remove(o),c.succeed("\u{1F680} Deployment submitted"),u.set("functionId",d.id,!0),await u.saveProjectConfig(),t.newline(),t.info(`Function ID: ${x.default.cyan(d.id)}`),t.info(`Status: ${gn(d.status)}`),s.wait===!1){t.newline(),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${x.default.cyan(`sinch functions status ${d.id}`)}`);return}await Wo(l,d.id)}catch(e){c.stop(),t.error(`Failed to deploy function: ${e.message}`),process.exit(1)}});async function Ho(s){let e=new Ci.default,n=process.cwd(),i=Je.default.join(bi.default.tmpdir(),`${s}-${Date.now()}.zip`),o=["node_modules","bin","obj",".git",".DS_Store","*.zip",".env",".env.local","npm-debug.log*",".sinch-tmp","examples","claude.md","readme.md",".vs",".vscode",".idea",".cursor","*.user","*.suo"];async function r(a,l=""){let p=await le.default.readdir(a);for(let d of p){let f=Je.default.join(a,d),g=Je.default.join(l,d).replace(/\\/g,"/");if(o.some(y=>d.match(new RegExp(y.replace("*",".*")))))continue;if((await le.default.stat(f)).isDirectory())await r(f,g);else{let y=await le.default.readFile(f);e.addFile(g,y)}}}return await r(n),e.writeZip(i),i}async function zo(s,e){let n={},i=null;try{i=await u.getCredentials()}catch(o){t.debug("Could not load credentials from secure storage: "+o.message)}if(s==="csharp"){let o=Je.default.join(process.cwd(),"appsettings.json");if(await le.default.pathExists(o))try{let r=await le.default.readJson(o);for(let a of Object.keys(r)){if(a==="Logging"||a==="AllowedHosts")continue;let l=r[a];if(l===""||l===null||l===void 0){let p="",d=!1;try{let g=(0,wt.execSync)("dotnet user-secrets list",{cwd:process.cwd(),encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim().split(`
51
+ `),e}async function pn(s,e){let n=Ee.resolve(e);await nt.writeFile(n,s,"utf8")}function mi(s){switch(Ee.extname(s).toLowerCase()){case".js":case".ts":return"node";case".py":return"python";case".cs":return"csharp";default:return"node"}}var nt,Ee,un=Q(()=>{"use strict";nt=h(require("fs-extra")),Ee=h(require("path"));z();k()});var Ii=R((nc,$i)=>{"use strict";var le=h(require("fs-extra")),Je=h(require("path")),x=h(require("chalk")),wi=require("commander");z();k();A();E();pi();ui();var Ci=h(require("adm-zip")),bi=h(require("os")),fn=h(require("inquirer")),wt=require("child_process"),Si=h(require("keytar")),vi=new wi.Command("deploy");vi.description("Deploy function to production").option("-n, --name <name>","Function name (default: current directory)").option("--no-wait","Don't wait for deployment to complete").option("--non-interactive","Use default values without prompting (auto-generates docs)").option("--no-docs","no doc generation").option("--private","Deploy to private namespace (internal access only, not publicly accessible)").action(async s=>{try{if(await u.load(),!u.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=u.getProjectConfig(),n=s.name||e.name,i=e.runtime;if(await Yo(e,s),i==="csharp"){let f=await le.default.readdir(process.cwd()).then(w=>w.filter(y=>y.endsWith(".csproj")));if(f.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");let g=f[0];await Xo(process.cwd(),g)}c.start("\u{1F4E6} Packaging function...");let o=await zo(n);c.succeed("\u{1F4E6} Function packaged"),c.start("\u{1F527} Preparing configuration...");let r=await Wo(i,n);c.succeed("\u{1F527} Configuration prepared");let a=await Qo(e,s);c.start("\u{1F680} Submitting deployment...");let l=new T(u.getApiConfig()),p=await le.default.readFile(o),d=await l.deployFunction(n,i,p,r,a);if(await le.default.remove(o),c.succeed("\u{1F680} Deployment submitted"),u.set("functionId",d.id,!0),await u.saveProjectConfig(),t.newline(),t.info(`Function ID: ${x.default.cyan(d.id)}`),t.info(`Status: ${gn(d.status)}`),s.wait===!1){t.newline(),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${x.default.cyan(`sinch functions status ${d.id}`)}`);return}await Go(l,d.id)}catch(e){c.stop(),t.error(`Failed to deploy function: ${e.message}`),process.exit(1)}});async function zo(s){let e=new Ci.default,n=process.cwd(),i=Je.default.join(bi.default.tmpdir(),`${s}-${Date.now()}.zip`),o=["node_modules","bin","obj",".git",".DS_Store","*.zip",".env",".env.local","npm-debug.log*",".sinch-tmp","examples","claude.md","readme.md",".vs",".vscode",".idea",".cursor","*.user","*.suo"];async function r(a,l=""){let p=await le.default.readdir(a);for(let d of p){let f=Je.default.join(a,d),g=Je.default.join(l,d).replace(/\\/g,"/");if(o.some(y=>d.match(new RegExp(y.replace("*",".*")))))continue;if((await le.default.stat(f)).isDirectory())await r(f,g);else{let y=await le.default.readFile(f);e.addFile(g,y)}}}return await r(n),e.writeZip(i),i}async function Wo(s,e){let n={},i=null;try{i=await u.getCredentials()}catch(o){t.debug("Could not load credentials from secure storage: "+o.message)}if(s==="csharp"){let o=Je.default.join(process.cwd(),"appsettings.json");if(await le.default.pathExists(o))try{let r=await le.default.readJson(o);for(let a of Object.keys(r)){if(a==="Logging"||a==="AllowedHosts")continue;let l=r[a];if(l===""||l===null||l===void 0){let p="",d=!1;try{let g=(0,wt.execSync)("dotnet user-secrets list",{cwd:process.cwd(),encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim().split(`
52
52
  `);for(let w of g){let y=w.match(/^([^=]+)\s*=\s*(.+)$/);if(y&&y[1]&&y[2]&&y[1].trim()===a){p=y[2].trim(),d=!0,t.debug(`Found ${a} in dotnet user-secrets`);break}}}catch{}!p&&i&&(a==="PROJECT_ID"&&i.projectId?p=i.projectId:a==="PROJECT_ID_API_KEY"&&i.keyId?p=i.keyId:a==="PROJECT_ID_API_SECRET"&&i.keySecret?(p=i.keySecret,d=!0):a==="VOICE_APPLICATION_KEY"&&i.applicationKey?p=i.applicationKey:a==="VOICE_APPLICATION_SECRET"&&i.applicationSecret&&(p=i.applicationSecret,d=!0)),p&&(n[a]={Value:p,Secret:d})}else n[a]={Value:String(l),Secret:!1}}}catch(r){t.debug("Could not read appsettings.json: "+r.message)}}else{let o=Je.default.join(process.cwd(),".env");if(await le.default.pathExists(o))try{let r=await le.default.readFile(o,"utf8"),a={};r.split(`
53
- `).forEach(p=>{if(p.trim()&&!p.trim().startsWith("#")){let[d,...f]=p.split("=");d&&(a[d.trim()]=f.join("=").trim())}});let l=["PORT","NODE_ENV","SINCH_TUNNEL"];for(let[p,d]of Object.entries(a))if(!l.includes(p))if(d===""||d===null||d===void 0){let f="",g=!1;if(i&&(p==="PROJECT_ID"&&i.projectId?f=i.projectId:p==="PROJECT_ID_API_KEY"&&i.keyId?f=i.keyId:p==="PROJECT_ID_API_SECRET"&&i.keySecret?(f=i.keySecret,g=!0):p==="VOICE_APPLICATION_KEY"&&i.applicationKey?f=i.applicationKey:p==="VOICE_APPLICATION_SECRET"&&i.applicationSecret&&(f=i.applicationSecret,g=!0)),!f)try{let w="sinch-functions-cli",y=`${e}-${p}`;f=await Si.default.getPassword(w,y)||"",f&&(g=!0,t.debug(`Loaded custom secret ${p} from keychain`))}catch(w){t.debug(`Could not load ${p} from keychain: ${w.message}`)}f&&(n[p]={Value:f,Secret:g})}else n[p]={Value:d,Secret:!1}}catch(r){t.debug("Could not read .env file: "+r.message)}}return n}async function Wo(s,e){let i=Date.now(),o=!1,r;return t.newline(),c.start("\u23F3 Connecting to deployment stream..."),new Promise((a,l)=>{let p,d;s.streamDeployment(e,f=>{let g=Math.floor((Date.now()-i)/1e3);switch(f.type){case"connected":c.text="\u23F3 Deployment stream connected, waiting for updates...";break;case"status":let w=f.data.data.message;c.text=`\u23F3 ${w} (${g}s)`;break;case"progress":let y=f.data.data.message,v=f.data.data.percentComplete;v?c.text=`\u23F3 ${y} (${v}%, ${g}s)`:c.text=`\u23F3 ${y} (${g}s)`;break;case"completed":o=!0,r=f.data.data.url,c.succeed("\u2705 Function deployed successfully"),s.getFunction(e).then(async P=>{if(t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${x.default.cyan(P.name)}`),t.info(` Status: ${gn("Running")}`),t.info(` URL: ${x.default.blue(r)}`),r){let D=await Lt(),C=await ln();if(D.isConversation){t.newline(),t.info("\u{1F4AC} Conversation Integration:");try{c.start("Updating Sinch Conversation webhook..."),await cn(r),c.succeed("Conversation webhook updated automatically"),t.info(` Webhook URL set to: ${x.default.cyan(r+"/conversation")}`)}catch(S){c.fail("Failed to update Conversation webhook");let b=S.response?.data?JSON.stringify(S.response.data):S.message;t.warn(` Error: ${b}`)}}if(C){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{c.start("Updating Sinch Voice callback URL..."),await an(r),c.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${x.default.cyan(r)}`)}catch(S){c.fail("Failed to update callback URL automatically"),t.warn(` Error: ${S.message}`),t.info(` Manual setup: ${x.default.cyan(`sinch voice callback-url ${r}`)}`)}}t.info(` Test function: ${x.default.cyan(`curl ${r}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${x.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`),p&&p(),d&&clearTimeout(d),a()}).catch(P=>{t.error(`Failed to get function details: ${P.message}`),p&&p(),d&&clearTimeout(d),a()});break;case"failed":o=!0;let $=f.data.data.errorMessage;c.fail("\u274C Deployment failed"),t.newline(),t.error("Deployment failed:"),$&&t.error(` ${$}`),t.newline(),t.info("\u{1F4A1} Troubleshooting:"),t.info(` \u2022 Check logs: ${x.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`),p&&p(),d&&clearTimeout(d),process.exit(1);break}},f=>{t.debug("SSE stream error, falling back to polling:",f),c.text="\u23F3 Deployment stream unavailable, checking status...",p&&p(),yi(s,e,i,3e5).then(a).catch(l)}).then(f=>{t.debug("SSE stream setup successful, cleanup function received"),p=f,d=setTimeout(()=>{o||(c.fail("\u23F0 Deployment timeout"),t.newline(),t.warn("Deployment is taking longer than expected"),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${x.default.cyan(`sinch functions status ${e}`)}`),p&&p(),a())},3e5)}).catch(f=>{t.debug(`Failed to set up SSE stream, falling back to polling: ${f.message}`),yi(s,e,i,3e5).then(a).catch(l)})})}async function yi(s,e,n,i){for(;Date.now()-n<i;){try{let a=(await s.getFunctionStatus(e)).function;if(a.status==="Running"){if(c.succeed("\u2705 Function deployed successfully"),t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${x.default.cyan(a.name)}`),t.info(` Status: ${gn(a.status)}`),t.info(` URL: ${x.default.blue(a.containerAppUrl)}`),a.containerAppUrl){let p=await Lt(),d=await ln();if(p.isConversation){t.newline(),t.info("\u{1F4AC} Conversation Integration:");try{c.start("Updating Sinch Conversation webhook..."),await cn(a.containerAppUrl),c.succeed("Conversation webhook updated automatically"),t.info(` Webhook URL set to: ${x.default.cyan(a.containerAppUrl+"/conversation")}`)}catch(f){c.fail("Failed to update Conversation webhook");let g=f.response?.data?JSON.stringify(f.response.data):f.message;t.warn(` Error: ${g}`)}}if(d){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{c.start("Updating Sinch Voice callback URL..."),await an(a.containerAppUrl),c.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${x.default.cyan(a.containerAppUrl)}`)}catch(f){c.fail("Failed to update callback URL automatically"),t.warn(` Error: ${f.message}`),t.info(` Manual setup: ${x.default.cyan(`sinch voice callback-url ${a.containerAppUrl}`)}`)}}t.info(` Test function: ${x.default.cyan(`curl ${a.containerAppUrl}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${x.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`);return}a.status==="Failed"&&(c.fail("\u274C Deployment failed"),t.newline(),t.error("Deployment failed:"),a.errorMessage&&t.error(` ${a.errorMessage}`),t.newline(),t.info("\u{1F4A1} Troubleshooting:"),t.info(` \u2022 Check logs: ${x.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`),process.exit(1));let l=Math.floor((Date.now()-n)/1e3);c.text=`\u23F3 Deploying function... (${a.status}, ${l}s)`}catch(r){t.debug(`Status check failed: ${r.message}`)}await new Promise(r=>setTimeout(r,3e3))}c.fail("\u23F0 Deployment timeout"),t.newline(),t.warn("Deployment is taking longer than expected"),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${x.default.cyan(`sinch functions status ${e}`)}`)}function gn(s){return{Running:x.default.green("\u2705 Running"),Failed:x.default.red("\u274C Failed"),Pending:x.default.yellow("\u23F3 Pending"),Building:x.default.blue("\u{1F528} Building")}[s]||x.default.gray(s)}async function Go(s,e){let n=!1;if(e.docs===!1){t.info("Skipping documentation generation (--no-docs flag)");return}if(e.nonInteractive)t.info("Generating documentation (non-interactive mode)"),n=!0;else{if(s.docsPreference==="never")return;if(Yo(s))n=!0;else{let i=await fn.default.prompt([{type:"list",name:"docsChoice",message:"Generate/update documentation before deployment?",choices:[{name:"Yes - Generate documentation this time",value:"yes"},{name:"No - Skip documentation this time",value:"no"},{name:"Always - Generate documentation and remember preference",value:"always"},{name:"Never - Don't generate documentation and remember preference",value:"never"}],default:"yes"}]);i.docsChoice==="yes"?n=!0:i.docsChoice==="no"?n=!1:i.docsChoice==="always"?(n=!0,u.set("docsPreference","always",!0),await u.saveProjectConfig()):i.docsChoice==="never"&&(n=!1,u.set("docsPreference","never",!0),await u.saveProjectConfig())}}if(n)try{c.start("\u{1F4DD} Generating documentation...");let{generateDocsFromLocal:i,saveDocumentationToFile:o}=(un(),M(hi)),r=await i(),a=Je.default.basename(process.cwd());await o(r,"README.md",a),c.succeed("\u{1F4DD} Documentation updated in README.md")}catch(i){c.warn(`\u26A0\uFE0F Failed to generate documentation: ${i.message}`),t.warn("Continuing with deployment...")}}function Yo(s){return s.docsPreference==="always"}async function Zo(s,e){if(e.private||s.accessPreference==="always-private")return"private";if(s.accessPreference==="always-public"||e.nonInteractive)return"public";let i=(await fn.default.prompt([{type:"list",name:"accessChoice",message:"Deployment access level?",choices:[{name:"Public - Accessible from the internet",value:"public"},{name:"Private - Internal access only (Sinch services)",value:"private"},{name:"Always Public - Remember this choice",value:"always-public"},{name:"Always Private - Remember this choice",value:"always-private"}],default:"public"}])).accessChoice;return i==="always-public"?(u.set("accessPreference","always-public",!0),await u.saveProjectConfig(),"public"):i==="always-private"?(u.set("accessPreference","always-private",!0),await u.saveProjectConfig(),"private"):i}async function Qo(s,e){c.start("Building function locally...");try{await new Promise((o,r)=>{let a=(0,wt.spawn)("dotnet",["build",e,"-c","Release"],{cwd:s,stdio:"pipe",shell:!0}),l="",p="";a.stdout?.on("data",d=>{p+=d}),a.stderr?.on("data",d=>{l+=d}),a.on("close",d=>{d!==0?r(new Error(`Build failed:
54
- ${l||p}`)):o()})}),c.succeed("Build successful")}catch(o){throw c.fail("Build failed"),o}c.start("Starting function for validation...");let n=null,i="";try{if(n=(0,wt.spawn)("dotnet",["run","--project",e,"--no-build","-c","Release"],{cwd:s,stdio:"pipe",shell:!0}),n.stdout?.on("data",r=>{i+=r.toString()}),n.stderr?.on("data",r=>{i+=r.toString()}),await Xo("http://localhost:3000/health",3e4))c.succeed("Function started and health check passed");else throw c.fail("Function failed to start within timeout"),i&&console.error(`
53
+ `).forEach(p=>{if(p.trim()&&!p.trim().startsWith("#")){let[d,...f]=p.split("=");d&&(a[d.trim()]=f.join("=").trim())}});let l=["PORT","NODE_ENV","SINCH_TUNNEL"];for(let[p,d]of Object.entries(a))if(!l.includes(p))if(d===""||d===null||d===void 0){let f="",g=!1;if(i&&(p==="PROJECT_ID"&&i.projectId?f=i.projectId:p==="PROJECT_ID_API_KEY"&&i.keyId?f=i.keyId:p==="PROJECT_ID_API_SECRET"&&i.keySecret?(f=i.keySecret,g=!0):p==="VOICE_APPLICATION_KEY"&&i.applicationKey?f=i.applicationKey:p==="VOICE_APPLICATION_SECRET"&&i.applicationSecret&&(f=i.applicationSecret,g=!0)),!f)try{let w="sinch-functions-cli",y=`${e}-${p}`;f=await Si.default.getPassword(w,y)||"",f&&(g=!0,t.debug(`Loaded custom secret ${p} from keychain`))}catch(w){t.debug(`Could not load ${p} from keychain: ${w.message}`)}f&&(n[p]={Value:f,Secret:g})}else n[p]={Value:d,Secret:!1}}catch(r){t.debug("Could not read .env file: "+r.message)}}return n}async function Go(s,e){let i=Date.now(),o=!1,r;return t.newline(),c.start("\u23F3 Connecting to deployment stream..."),new Promise((a,l)=>{let p,d;s.streamDeployment(e,f=>{let g=Math.floor((Date.now()-i)/1e3);switch(f.type){case"connected":c.text="\u23F3 Deployment stream connected, waiting for updates...";break;case"status":let w=f.data.data.message;c.text=`\u23F3 ${w} (${g}s)`;break;case"progress":let y=f.data.data.message,v=f.data.data.percentComplete;v?c.text=`\u23F3 ${y} (${v}%, ${g}s)`:c.text=`\u23F3 ${y} (${g}s)`;break;case"completed":o=!0,r=f.data.data.url,c.succeed("\u2705 Function deployed successfully"),s.getFunction(e).then(async P=>{if(t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${x.default.cyan(P.name)}`),t.info(` Status: ${gn("Running")}`),t.info(` URL: ${x.default.blue(r)}`),r){let D=await Lt(),C=await ln();if(D.isConversation){t.newline(),t.info("\u{1F4AC} Conversation Integration:");try{c.start("Updating Sinch Conversation webhook..."),await cn(r),c.succeed("Conversation webhook updated automatically"),t.info(` Webhook URL set to: ${x.default.cyan(r+"/conversation")}`)}catch(S){c.fail("Failed to update Conversation webhook");let b=S.response?.data?JSON.stringify(S.response.data):S.message;t.warn(` Error: ${b}`)}}if(C){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{c.start("Updating Sinch Voice callback URL..."),await an(r),c.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${x.default.cyan(r)}`)}catch(S){c.fail("Failed to update callback URL automatically"),t.warn(` Error: ${S.message}`),t.info(` Manual setup: ${x.default.cyan(`sinch voice callback-url ${r}`)}`)}}t.info(` Test function: ${x.default.cyan(`curl ${r}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${x.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`),p&&p(),d&&clearTimeout(d),a()}).catch(P=>{t.error(`Failed to get function details: ${P.message}`),p&&p(),d&&clearTimeout(d),a()});break;case"failed":o=!0;let $=f.data.data.errorMessage;c.fail("\u274C Deployment failed"),t.newline(),t.error("Deployment failed:"),$&&t.error(` ${$}`),t.newline(),t.info("\u{1F4A1} Troubleshooting:"),t.info(` \u2022 Check logs: ${x.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`),p&&p(),d&&clearTimeout(d),process.exit(1);break}},f=>{t.debug("SSE stream error, falling back to polling:",f),c.text="\u23F3 Deployment stream unavailable, checking status...",p&&p(),yi(s,e,i,3e5).then(a).catch(l)}).then(f=>{t.debug("SSE stream setup successful, cleanup function received"),p=f,d=setTimeout(()=>{o||(c.fail("\u23F0 Deployment timeout"),t.newline(),t.warn("Deployment is taking longer than expected"),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${x.default.cyan(`sinch functions status ${e}`)}`),p&&p(),a())},3e5)}).catch(f=>{t.debug(`Failed to set up SSE stream, falling back to polling: ${f.message}`),yi(s,e,i,3e5).then(a).catch(l)})})}async function yi(s,e,n,i){for(;Date.now()-n<i;){try{let a=(await s.getFunctionStatus(e)).function;if(a.status==="Running"){if(c.succeed("\u2705 Function deployed successfully"),t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${x.default.cyan(a.name)}`),t.info(` Status: ${gn(a.status)}`),t.info(` URL: ${x.default.blue(a.containerAppUrl)}`),a.containerAppUrl){let p=await Lt(),d=await ln();if(p.isConversation){t.newline(),t.info("\u{1F4AC} Conversation Integration:");try{c.start("Updating Sinch Conversation webhook..."),await cn(a.containerAppUrl),c.succeed("Conversation webhook updated automatically"),t.info(` Webhook URL set to: ${x.default.cyan(a.containerAppUrl+"/conversation")}`)}catch(f){c.fail("Failed to update Conversation webhook");let g=f.response?.data?JSON.stringify(f.response.data):f.message;t.warn(` Error: ${g}`)}}if(d){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{c.start("Updating Sinch Voice callback URL..."),await an(a.containerAppUrl),c.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${x.default.cyan(a.containerAppUrl)}`)}catch(f){c.fail("Failed to update callback URL automatically"),t.warn(` Error: ${f.message}`),t.info(` Manual setup: ${x.default.cyan(`sinch voice callback-url ${a.containerAppUrl}`)}`)}}t.info(` Test function: ${x.default.cyan(`curl ${a.containerAppUrl}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${x.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`);return}a.status==="Failed"&&(c.fail("\u274C Deployment failed"),t.newline(),t.error("Deployment failed:"),a.errorMessage&&t.error(` ${a.errorMessage}`),t.newline(),t.info("\u{1F4A1} Troubleshooting:"),t.info(` \u2022 Check logs: ${x.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${x.default.cyan(`sinch functions status ${e}`)}`),process.exit(1));let l=Math.floor((Date.now()-n)/1e3);c.text=`\u23F3 Deploying function... (${a.status}, ${l}s)`}catch(r){t.debug(`Status check failed: ${r.message}`)}await new Promise(r=>setTimeout(r,3e3))}c.fail("\u23F0 Deployment timeout"),t.newline(),t.warn("Deployment is taking longer than expected"),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${x.default.cyan(`sinch functions status ${e}`)}`)}function gn(s){return{Running:x.default.green("\u2705 Running"),Failed:x.default.red("\u274C Failed"),Pending:x.default.yellow("\u23F3 Pending"),Building:x.default.blue("\u{1F528} Building")}[s]||x.default.gray(s)}async function Yo(s,e){let n=!1;if(e.docs===!1){t.info("Skipping documentation generation (--no-docs flag)");return}if(e.nonInteractive)t.info("Generating documentation (non-interactive mode)"),n=!0;else{if(s.docsPreference==="never")return;if(Zo(s))n=!0;else{let i=await fn.default.prompt([{type:"list",name:"docsChoice",message:"Generate/update documentation before deployment?",choices:[{name:"Yes - Generate documentation this time",value:"yes"},{name:"No - Skip documentation this time",value:"no"},{name:"Always - Generate documentation and remember preference",value:"always"},{name:"Never - Don't generate documentation and remember preference",value:"never"}],default:"yes"}]);i.docsChoice==="yes"?n=!0:i.docsChoice==="no"?n=!1:i.docsChoice==="always"?(n=!0,u.set("docsPreference","always",!0),await u.saveProjectConfig()):i.docsChoice==="never"&&(n=!1,u.set("docsPreference","never",!0),await u.saveProjectConfig())}}if(n)try{c.start("\u{1F4DD} Generating documentation...");let{generateDocsFromLocal:i,saveDocumentationToFile:o}=(un(),M(hi)),r=await i(),a=Je.default.basename(process.cwd());await o(r,"README.md",a),c.succeed("\u{1F4DD} Documentation updated in README.md")}catch(i){c.warn(`\u26A0\uFE0F Failed to generate documentation: ${i.message}`),t.warn("Continuing with deployment...")}}function Zo(s){return s.docsPreference==="always"}async function Qo(s,e){if(e.private||s.accessPreference==="always-private")return"private";if(s.accessPreference==="always-public"||e.nonInteractive)return"public";let i=(await fn.default.prompt([{type:"list",name:"accessChoice",message:"Deployment access level?",choices:[{name:"Public - Accessible from the internet",value:"public"},{name:"Private - Internal access only (Sinch services)",value:"private"},{name:"Always Public - Remember this choice",value:"always-public"},{name:"Always Private - Remember this choice",value:"always-private"}],default:"public"}])).accessChoice;return i==="always-public"?(u.set("accessPreference","always-public",!0),await u.saveProjectConfig(),"public"):i==="always-private"?(u.set("accessPreference","always-private",!0),await u.saveProjectConfig(),"private"):i}async function Xo(s,e){c.start("Building function locally...");try{await new Promise((o,r)=>{let a=(0,wt.spawn)("dotnet",["build",e,"-c","Release"],{cwd:s,stdio:"pipe",shell:!0}),l="",p="";a.stdout?.on("data",d=>{p+=d}),a.stderr?.on("data",d=>{l+=d}),a.on("close",d=>{d!==0?r(new Error(`Build failed:
54
+ ${l||p}`)):o()})}),c.succeed("Build successful")}catch(o){throw c.fail("Build failed"),o}c.start("Starting function for validation...");let n=null,i="";try{if(n=(0,wt.spawn)("dotnet",["run","--project",e,"--no-build","-c","Release"],{cwd:s,stdio:"pipe",shell:!0}),n.stdout?.on("data",r=>{i+=r.toString()}),n.stderr?.on("data",r=>{i+=r.toString()}),await er("http://localhost:3000/health",3e4))c.succeed("Function started and health check passed");else throw c.fail("Function failed to start within timeout"),i&&console.error(`
55
55
  Process output:
56
56
  `+i),new Error("Function validation failed: could not start function")}catch(o){throw c.fail("Validation failed"),i&&console.error(`
57
57
  Process output:
58
- `+i),o}finally{if(n&&n.pid){try{process.kill(n.pid)}catch{}await new Promise(o=>setTimeout(o,1e3))}}}async function Xo(s,e){let n=Date.now();for(;Date.now()-n<e;){try{if((await fetch(s)).ok)return!0}catch{}await new Promise(i=>setTimeout(i,500))}return!1}$i.exports=vi});var xi=R((rc,Ei)=>{"use strict";var U=h(require("fs-extra")),fe=h(require("path")),Ct=h(require("chalk")),mn=require("child_process"),ki=require("commander"),Pi=h(require("inquirer"));k();A();E();var Ai=new ki.Command("dev");Ai.description("Start local development server").option("-p, --port <port>","Port to run on","3000").option("-d, --debug","Enable debugging with --inspect").option("--tunnel","Force tunnel creation").option("--no-tunnel",'Disable tunnel and reset "always" preference').action(async s=>{try{if(await u.load(),!u.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=u.getProjectConfig();if(!e)throw new Error("No project configuration found");let n=e.runtime||"node",i;if(n==="csharp"){let o=await U.default.readdir(process.cwd()).then(r=>r.filter(a=>a.endsWith(".csproj")));if(o.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");i=o[0],t.debug(`Using project file: ${i}`)}else{let o=fe.default.join(process.cwd(),"node_modules",".bin","sinch-runtime");if(!await U.default.pathExists(o))throw new Error("@sinch/functions-runtime not found. Run npm install first.")}t.title(`Starting ${e.name} (${e.runtime})`),t.info(`Port: ${s.port}`),t.newline(),await tr(s,e,i)}catch(e){c.stop(),t.error(`Failed to start development server: ${e.message}`),process.exit(1)}});async function er(s,e){if(e==="node"){let n=fe.default.join(process.cwd(),".env");if(await U.default.pathExists(n)){let i=await U.default.readFile(n,"utf-8"),o=`SINCH_TUNNEL=${s}`;i.includes("SINCH_TUNNEL=")?i=i.replace(/SINCH_TUNNEL=(true|false)/g,o):i+=`
58
+ `+i),o}finally{if(n&&n.pid){try{process.kill(n.pid)}catch{}await new Promise(o=>setTimeout(o,1e3))}}}async function er(s,e){let n=Date.now();for(;Date.now()-n<e;){try{if((await fetch(s)).ok)return!0}catch{}await new Promise(i=>setTimeout(i,500))}return!1}$i.exports=vi});var xi=R((ac,Ei)=>{"use strict";var U=h(require("fs-extra")),fe=h(require("path")),Ct=h(require("chalk")),mn=require("child_process"),ki=require("commander"),Pi=h(require("inquirer"));k();A();E();var Ai=new ki.Command("dev");Ai.description("Start local development server").option("-p, --port <port>","Port to run on","3000").option("-d, --debug","Enable debugging with --inspect").option("--tunnel","Force tunnel creation").option("--no-tunnel",'Disable tunnel and reset "always" preference').action(async s=>{try{if(await u.load(),!u.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=u.getProjectConfig();if(!e)throw new Error("No project configuration found");let n=e.runtime||"node",i;if(n==="csharp"){let o=await U.default.readdir(process.cwd()).then(r=>r.filter(a=>a.endsWith(".csproj")));if(o.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");i=o[0],t.debug(`Using project file: ${i}`)}else{let o=fe.default.join(process.cwd(),"node_modules",".bin","sinch-runtime");if(!await U.default.pathExists(o))throw new Error("@sinch/functions-runtime not found. Run npm install first.")}t.title(`Starting ${e.name} (${e.runtime})`),t.info(`Port: ${s.port}`),t.newline(),await nr(s,e,i)}catch(e){c.stop(),t.error(`Failed to start development server: ${e.message}`),process.exit(1)}});async function tr(s,e){if(e==="node"){let n=fe.default.join(process.cwd(),".env");if(await U.default.pathExists(n)){let i=await U.default.readFile(n,"utf-8"),o=`SINCH_TUNNEL=${s}`;i.includes("SINCH_TUNNEL=")?i=i.replace(/SINCH_TUNNEL=(true|false)/g,o):i+=`
59
59
  ${o}
60
- `,await U.default.writeFile(n,i,"utf-8"),t.debug(`Updated .env: SINCH_TUNNEL=${s}`)}}else if(e==="csharp"){let n=fe.default.join(process.cwd(),"appsettings.Development.json");if(await U.default.pathExists(n)){let i=await U.default.readJson(n);i.SinchTunnel=s,await U.default.writeJson(n,i,{spaces:2}),t.debug(`Updated appsettings.Development.json: SinchTunnel=${s}`)}}}async function tr(s,e,n){let i=e.runtime||"node",o=!1;if(s.tunnel===!0)o=!0;else if(s.tunnel===!1)o=!1,e.tunnel?.preference==="always"&&(u.set("tunnel",{...e.tunnel,preference:"no"},!0),await u.saveProjectConfig());else if(e.tunnel?.preference==="never")o=!1;else if(or(e))o=!0;else{let{tunnelChoice:d}=await Pi.default.prompt([{type:"list",name:"tunnelChoice",message:"Enable Sinch tunnel for external access?",choices:[{name:"Yes - Enable tunnel this time",value:"yes"},{name:"No - Local only this time",value:"no"},{name:"Always - Enable tunnel and remember preference",value:"always"},{name:"Never - Don't enable tunnel and remember preference",value:"never"}],default:"no"}]);d==="yes"?o=!0:d==="no"?o=!1:d==="always"?(o=!0,u.set("tunnel",{...e.tunnel,preference:"always"},!0),await u.saveProjectConfig()):d==="never"&&(o=!1,u.set("tunnel",{...e.tunnel,preference:"never"},!0),await u.saveProjectConfig())}await er(o,i);let r={...process.env,PORT:s.port,NODE_ENV:"development",SINCH_FUNCTIONS_LOCAL:"true",SINCH_TUNNEL:o?"true":"false"};e.variables&&Object.entries(e.variables).forEach(([d,f])=>{r[d]=f});try{let d=await u.getApplicationCredentials(e.voiceAppKey);d?(r.SINCH_APPLICATION_KEY=d.applicationKey,r.SINCH_APPLICATION_SECRET=d.applicationSecret,t.debug("\u2705 Injected application credentials for voice operations")):t.debug("\u26A0\uFE0F No application credentials found - voice features may not work")}catch(d){t.debug(`\u26A0\uFE0F Could not load application credentials: ${d.message}`)}t.info("\u{1F680} Starting local server...");let a=null,l=!1;function p(){if(a&&a.kill(),i==="csharp"){let d=["watch","run","--no-launch-profile"];n&&d.push("--project",n),s.port&&d.push("--urls",`http://localhost:${s.port}`),r.ASPNETCORE_ENVIRONMENT="Development",r.ASPNETCORE_URLS=`http://localhost:${s.port}`,a=(0,mn.spawn)("dotnet",d,{env:r,stdio:"inherit",cwd:process.cwd()})}else a=(0,mn.spawn)("npm",["run","dev"],{env:r,stdio:"inherit",cwd:process.cwd(),shell:!0});a.on("spawn",async()=>{if(!l){l=!0,t.newline(),t.success(`\u2705 Server running on http://localhost:${s.port}`),s.debug&&(t.newline(),i==="csharp"?rr():nr()),t.newline(),t.info("\u{1F4A1} Development commands:"),t.info(` \u2022 Test function: ${Ct.default.cyan(`curl http://localhost:${s.port}`)}`),t.info(` \u2022 View in browser: ${Ct.default.cyan(`http://localhost:${s.port}`)}`),t.info(` \u2022 Stop server: ${Ct.default.gray("Ctrl+C")}`);let d=i==="csharp"?"dotnet watch":"nodemon";t.info(` \u2022 File watching: ${Ct.default.green(`enabled (via ${d})`)}`)}}),a.on("error",d=>{t.error(`Server error: ${d.message}`)}),a.on("exit",(d,f)=>{f!=="SIGTERM"&&f!=="SIGKILL"&&t.error(`Server exited with code ${d}`)})}p(),process.on("SIGINT",()=>{t.newline(),t.info("\u{1F534} Stopping development server..."),a&&a.kill("SIGTERM"),process.exit(0)}),await new Promise(()=>{})}async function nr(){try{let s=await it("code",".vscode"),e=await it("cursor",".cursor"),n=await it("webstorm",".idea");if(s||e){let i=s?"VS Code":"Cursor",o=".vscode";if(t.info(`\u{1F41B} ${i} detected! Debug setup:`),await sr(o))t.info(" 1. \u2705 Created .vscode/launch.json for you");else{let a=fe.default.join(process.cwd(),o,"launch.json");await U.default.pathExists(a)?t.info(" 1. \u2705 Found existing .vscode/launch.json"):t.info(" 1. \u26A0\uFE0F Could not create .vscode/launch.json")}t.info(" 2. \u{1F50D} Press F5 to attach debugger"),t.info(" 3. \u{1F534} Set breakpoints in your function.js"),t.info(" 4. \u{1F4DE} Test your function to hit breakpoints")}else n?(t.info("\u{1F41B} WebStorm detected! Debug setup:"),t.info(" 1. \u{1F50D} Run \u2192 Attach to Node.js/Chrome \u2192 localhost:9229"),t.info(" 2. \u{1F534} Set breakpoints in your function.js")):(t.info("\u{1F41B} Manual debug setup:"),t.info(' \u2022 VS Code/Cursor: Open "Run and Debug" \u2192 "Attach to Node.js Process"'),t.info(' \u2022 Chrome DevTools: Visit chrome://inspect \u2192 Click "inspect"'),t.info(" \u2022 Manual: Connect debugger to ws://localhost:9229"))}catch{t.info("\u{1F41B} Debug instructions:"),t.info(" \u2022 Connect your debugger to ws://localhost:9229"),t.info(" \u2022 Set breakpoints and test your function")}}async function it(s,e){try{if(s==="code"&&ir())return!0;let{spawn:n}=require("child_process"),i=await new Promise(r=>{let a=n(s,["--version"],{stdio:"pipe"});a.on("close",l=>r(l===0)),a.on("error",()=>r(!1))}),o=e?await U.default.pathExists(e):!1;return i||o}catch{return!1}}function ir(){return process.env.TERM_PROGRAM==="vscode"||!!process.env.VSCODE_IPC_HOOK||!!process.env.VSCODE_PID}async function sr(s=".vscode"){try{let e=fe.default.join(process.cwd(),s),n=fe.default.join(e,"launch.json");if(await U.default.pathExists(n))return!1;await U.default.ensureDir(e);let i={version:"0.2.0",configurations:[{name:"Attach to Sinch Function",type:"node",request:"attach",port:9229,localRoot:"${workspaceFolder}",remoteRoot:"${workspaceFolder}",skipFiles:["<node_internals>/**","node_modules/**"]}]};return await U.default.writeJson(n,i,{spaces:2}),!!await U.default.pathExists(n)}catch{return!1}}function or(s){return s.tunnel?s.tunnel.preference==="always":!1}async function rr(){try{let s=await it("code",".vscode"),e=await it("devenv"),n=await it("rider",".idea");s?(t.info("\u{1F41B} VS Code detected! Debug setup:"),await ar(".vscode")?t.info(" 1. \u2705 Created .vscode/launch.json for C#"):t.info(" 1. \u2705 Found existing .vscode/launch.json"),t.info(" 2. \u{1F50D} Press F5 to attach debugger"),t.info(" 3. \u{1F534} Set breakpoints in your Function.cs"),t.info(" 4. \u{1F4DE} Test your function to hit breakpoints")):e?(t.info("\u{1F41B} Visual Studio detected! Debug setup:"),t.info(" 1. \u{1F50D} Debug \u2192 Attach to Process \u2192 dotnet.exe"),t.info(" 2. \u{1F534} Set breakpoints in your Function.cs"),t.info(" 3. \u{1F4DE} Test your function to hit breakpoints")):n?(t.info("\u{1F41B} JetBrains Rider detected! Debug setup:"),t.info(" 1. \u{1F50D} Run \u2192 Attach to Process \u2192 dotnet"),t.info(" 2. \u{1F534} Set breakpoints in your Function.cs")):(t.info("\u{1F41B} C# Debug setup:"),t.info(" \u2022 Visual Studio: Debug \u2192 Attach to Process \u2192 dotnet.exe"),t.info(" \u2022 VS Code: Install C# extension, then F5 to debug"),t.info(" \u2022 Rider: Run \u2192 Attach to Process"))}catch{t.info("\u{1F41B} C# Debug instructions:"),t.info(" \u2022 Attach your debugger to the dotnet process"),t.info(" \u2022 Set breakpoints in Function.cs")}}async function ar(s=".vscode"){try{let e=fe.default.join(process.cwd(),s),n=fe.default.join(e,"launch.json");if(await U.default.pathExists(n))return!1;await U.default.ensureDir(e);let i={version:"0.2.0",configurations:[{name:".NET Core Launch (web)",type:"coreclr",request:"launch",preLaunchTask:"build",program:"${workspaceFolder}/bin/Debug/net8.0/Function.dll",args:[],cwd:"${workspaceFolder}",stopAtEntry:!1,serverReadyAction:{action:"openExternally",pattern:"\\bNow listening on:\\s+(https?://\\S+)"},env:{ASPNETCORE_ENVIRONMENT:"Development"},sourceFileMap:{"/Views":"${workspaceFolder}/Views"}},{name:".NET Core Attach",type:"coreclr",request:"attach"}]};await U.default.writeJson(n,i,{spaces:2});let o=fe.default.join(e,"tasks.json");if(!await U.default.pathExists(o)){let r={version:"2.0.0",tasks:[{label:"build",command:"dotnet",type:"process",args:["build","${workspaceFolder}/Function.csproj","/property:GenerateFullPaths=true","/consoleloggerparameters:NoSummary"],problemMatcher:"$msCompile"}]};await U.default.writeJson(o,r,{spaces:2})}return await U.default.pathExists(n)}catch{return!1}}Ei.exports=Ai});var Oi=R((pc,Ni)=>{"use strict";var ee=h(require("chalk")),Di=require("commander");z();k();A();E();var ji=new Di.Command("status");ji.description("Show function status and details").argument("[function-id]","Function ID to check (optional if sinch.json exists)").option("-f, --follow","Watch status changes in real-time").option("--json","Output raw JSON").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig()),i=s;if(!i){if(!u.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");if(i=u.getProjectConfig()?.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}e.follow?await lr(n,i):await cr(n,i,e)}catch(n){c.stop(),t.error(`Failed to get function status: ${n.message}`),process.exit(1)}});async function cr(s,e,n){c.start("\u{1F4E1} Loading function status...");try{let i=await s.getFunction(e),o=await s.getFunctionStatus(e);if(c.stop(),n.json){console.log(JSON.stringify({function:i,deployment:o},null,2));return}let r=i,a=o.status,l=o.error;t.newline(),t.title(`Function Status: ${r.name}`),t.newline(),t.info("\u{1F4CB} Function Details:"),t.info(` ID: ${ee.default.gray(r.id)}`),t.info(` Name: ${ee.default.cyan(r.name)}`),t.info(` Runtime: ${ee.default.yellow(r.runtime)}`),t.info(` Deployment Status: ${Ri(a)}`),r.created&&t.info(` Created: ${new Date(r.created).toLocaleString()}`),r.updated&&t.info(` Updated: ${new Date(r.updated).toLocaleString()}`),r.url&&t.info(` URL: ${ee.default.blue(r.url)}`),a==="Failed"&&l&&(t.newline(),t.error("Deployment Error:"),t.error(` ${l}`)),t.newline(),t.info("\u{1F4A1} Commands:"),t.info(` \u2022 View logs: ${ee.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Redeploy: ${ee.default.cyan("sinch functions deploy")}`),t.info(` \u2022 Delete: ${ee.default.cyan(`sinch functions delete ${e}`)}`)}catch(i){throw c.stop(),i}}async function lr(s,e){t.info("\u{1F440} Watching deployment status (press Ctrl+C to stop)..."),t.newline();let n=null,i=setInterval(async()=>{try{let o=await s.getFunctionStatus(e),r=o.status;if(r!==n){let a=new Date().toLocaleTimeString();if(t.info(`[${a}] Status: ${Ri(r)}`),n=r,r==="Running"){t.success("Function deployment is now running!");try{let l=await s.getFunction(e);l.url&&t.info(`URL: ${ee.default.blue(l.url)}`)}catch{}}else r==="Failed"&&(t.error("Function deployment failed!"),o.error&&t.error(`Error: ${o.error}`),clearInterval(i))}}catch(o){t.error(`Error checking status: ${o.message}`)}},3e3);process.on("SIGINT",()=>{clearInterval(i),t.newline(),t.info("Stopped watching function status"),process.exit(0)})}function Ri(s){return{Running:ee.default.green("\u2705 Running"),Failed:ee.default.red("\u274C Failed"),Pending:ee.default.yellow("\u23F3 Pending"),Building:ee.default.blue("\u{1F528} Building")}[s]||ee.default.gray(s)}Ni.exports=ji});var Bi=R((hc,Ji)=>{"use strict";var Be=h(require("chalk")),Li=require("commander");z();k();A();E();var hn=require("child_process"),bt=h(require("fs")),St=h(require("os")),vt=h(require("path")),yn=new Li.Command("logs");yn.description("View function logs").argument("[function-id]","Function ID to get logs for (optional if sinch.json exists)").option("-f, --follow","Follow log output in real-time").option("-n, --lines <number>","Number of historical lines to show","50").option("--level <level>","Filter by log level (debug, info, warning, error)").option("--search <text>","Search for text in log messages").option("--since <duration>","Show logs since duration (e.g., 1h, 30m, 5s)").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig()),i=s;if(!i){if(!u.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let r=u.getProjectConfig();if(!r)throw new Error("No project configuration found");if(i=r.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}c.start("Loading function details...");let o=await n.getFunction(i);c.stop(),t.info(`\u{1F4CB} Logs for function: ${Be.default.cyan(o.name)} (${pr(o.status)})`),t.newline(),e.follow?await _i(n,i,o.name,e):await Sr(n,i,e)}catch(n){c.stop(),t.error(`Failed to get logs: ${n.message}`),process.exit(1)}});yn.command("stream").description("Stream function logs in real-time").argument("[function-id]","Function ID to stream logs for (optional if sinch.json exists)").option("--level <level>","Filter by log level (debug, info, warning, error)").option("--search <text>","Search for text in log messages").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig()),i=s;if(!i){if(!u.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let r=u.getProjectConfig();if(!r)throw new Error("No project configuration found");if(i=r.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}c.start("Connecting to log stream...");let o=await dr(n,i);c.stop(),await _i(n,i,o.name,{...e,follow:!0})}catch(n){c.stop(),t.error(`Failed to stream logs: ${n.message}`),process.exit(1)}});async function dr(s,e){return await s.getFunction(e)}async function _i(s,e,n,i){let o=s.baseUrl.replace(/\/+$/,""),r=s.projectId,a=`${o}/v1/projects/${r}/functions/${e}/logs/stream`,l=s.credentials,p=[],d=qi(p,"STREAMING",n),f={Accept:"text/event-stream","Cache-Control":"no-cache"};if(l)try{let w=await l.retrieve();if(w&&w.keyId&&w.keySecret){let y=Buffer.from(`${w.keyId}:${w.keySecret}`).toString("base64");f.Authorization=`Basic ${y}`}}catch(w){t.debug("Failed to add authentication:",w)}let g=new AbortController;try{let w=await fetch(a,{method:"GET",headers:f,signal:g.signal});if(!w.ok)throw new Error(`SSE connection failed: ${w.status} ${w.statusText}`);if(!w.body)throw new Error("Response body is null");Ti(d.statusBar,"CONNECTED",n),d.screen.render();let y=w.body.getReader(),v=new TextDecoder,$="";(async()=>{try{for(;;){let{done:D,value:C}=await y.read();if(D)break;$+=v.decode(C,{stream:!0});let S=$.split(`
61
- `);$=S.pop()||"";for(let b of S)if(!b.startsWith("event:")&&b.startsWith("data:")){let I=b.substring(5).trim();if(I)try{let _=JSON.parse(I);_.type==="request"&&_.request&&(p.push(_.request),Ui(d.table,_.request,p),d.table.focus(),d.screen.render())}catch{}}}}catch(D){D.name!=="AbortError"&&(Ti(d.statusBar,"RECONNECTING",n),d.screen.render())}})(),d.screen.key(["q","C-c"],()=>{g.abort(),process.exit(0)}),await new Promise(()=>{})}catch(w){g.abort(),t.error(`\u274C Streaming failed: ${w.message}`),process.exit(1)}}function pr(s){return{Running:Be.default.green("\u2705 Running"),Failed:Be.default.red("\u274C Failed"),Pending:Be.default.yellow("\u23F3 Pending"),Building:Be.default.blue("\u{1F528} Building")}[s]||Be.default.gray(s)}var Ke=[];function Ui(s,e,n){let i=new Date(e.startTime),o=i.getFullYear()+"-"+String(i.getMonth()+1).padStart(2,"0")+"-"+String(i.getDate()).padStart(2,"0")+" "+String(i.getHours()).padStart(2,"0")+":"+String(i.getMinutes()).padStart(2,"0")+":"+String(i.getSeconds()).padStart(2,"0"),r=br(e),a=`${e.executionTimeMs}ms`,l=e.statusCode.toString(),p=process.stdout.columns||120,f=Math.max(30,p-35),g=e.url.length>f?e.url.substring(0,f-2)+"..":e.url;Ke.push([o,r,a,l,g]),Ke.length>100&&(Ke=Ke.slice(-100),n&&n.length>100&&n.splice(0,n.length-100));let w=[["Time","Callback","Duration","Status","Path"],...Ke];s.setData(w)}function ur(s,e,n,i,o){try{let r=require("blessed");t.debug(`Showing request details for ${s.httpMethod} ${s.url}`);let a=r.box({parent:e,top:0,left:0,width:"100%",height:"100%",border:{type:"line"},style:{border:{fg:"cyan"},bg:"black",fg:"white"},scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,label:" Request Details "}),l=r.box({parent:a,top:1,left:2,width:"100%-4",height:1,content:"{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J/1] JSON [C/2] cURL{/}",tags:!0,style:{bg:"blue",fg:"white"}});r.box({parent:a,top:2,left:2,width:"100%-4",height:1,content:`{bold}{cyan-fg}${s.httpMethod}{/} {blue-fg}${s.url}{/} - {${wr(s.statusCode)}}${s.statusCode}{/} - {yellow-fg}${s.executionTimeMs}ms{/} - {magenta-fg}${s.memoryUsedMB||0}MB{/}`,tags:!0,style:{bg:"black"}});let p=r.box({parent:a,top:4,left:2,width:"100%-4",height:"100%-5",scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,content:fr(s)});p.focus(),e.render();let d=!0,f=()=>{d&&(d=!1,a.destroy(),n.focus(),e.render())};e.key(["escape","q"],()=>{d&&f()}),e.key(["up","k"],()=>{d&&(p.scroll(-1),e.render())}),e.key(["down","j"],()=>{d&&(p.scroll(1),e.render())}),e.on("keypress",(g,w)=>{d&&t.debug(`Key pressed: ch="${g}" key=${JSON.stringify(w)}`)}),e.key(["J","j"],()=>{d&&(t.debug("J/j key pressed - attempting JSON copy"),l.setContent("{black-bg}{yellow-fg} J KEY PRESSED - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let g=JSON.stringify(s,null,2);t.debug(`JSON content length: ${g.length}`),t.debug("Attempting native clipboard copy"),_t(g).then(()=>{l.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{t.debug(`Native clipboard failed: ${w.message}`);let y=vt.default.join(St.default.tmpdir(),`sinch-request-${Date.now()}.json`);bt.default.writeFileSync(y,g),l.setContent(`{yellow-fg}\u2713 JSON saved to: ${y}{/}`),t.debug(`Saved to temp file: ${y}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(g){t.debug(`JSON copy error: ${g.message}`),l.setContent(`{red-fg}\u2717 Copy failed: ${g.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["C","c"],()=>{d&&(t.debug("C/c key pressed - attempting cURL copy"),l.setContent("{black-bg}{yellow-fg} C KEY PRESSED - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let g=Fi(s);t.debug("Attempting native clipboard copy for cURL"),_t(g).then(()=>{l.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded for cURL"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{t.debug(`Native clipboard failed for cURL: ${w.message}`);let y=vt.default.join(St.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);bt.default.writeFileSync(y,g),l.setContent(`{yellow-fg}\u2713 cURL saved to: ${y}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(g){t.debug(`cURL copy error: ${g.message}`),l.setContent(`{red-fg}\u2717 Copy failed: ${g.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["1"],()=>{d&&(t.debug("1 key pressed - copying JSON (alternative binding)"),l.setContent("{black-bg}{yellow-fg} 1 KEY - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let g=JSON.stringify(s,null,2);_t(g).then(()=>{l.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{let y=vt.default.join(St.default.tmpdir(),`sinch-request-${Date.now()}.json`);bt.default.writeFileSync(y,g),l.setContent(`{yellow-fg}\u2713 JSON saved to: ${y}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(g){l.setContent(`{red-fg}\u2717 Copy failed: ${g.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["2"],()=>{d&&(t.debug("2 key pressed - copying cURL (alternative binding)"),l.setContent("{black-bg}{yellow-fg} 2 KEY - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let g=Fi(s);_t(g).then(()=>{l.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{let y=vt.default.join(St.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);bt.default.writeFileSync(y,g),l.setContent(`{yellow-fg}\u2713 cURL saved to: ${y}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(g){l.setContent(`{red-fg}\u2717 Copy failed: ${g.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))})}catch(r){t.debug(`Error in showBlessedZoomedRequest: ${r.message}`)}}function fr(s){let e="";return e+=`
62
- `,e+=gr(s),e+=`
60
+ `,await U.default.writeFile(n,i,"utf-8"),t.debug(`Updated .env: SINCH_TUNNEL=${s}`)}}else if(e==="csharp"){let n=fe.default.join(process.cwd(),"appsettings.Development.json");if(await U.default.pathExists(n)){let i=await U.default.readJson(n);i.SinchTunnel=s,await U.default.writeJson(n,i,{spaces:2}),t.debug(`Updated appsettings.Development.json: SinchTunnel=${s}`)}}}async function nr(s,e,n){let i=e.runtime||"node",o=!1;if(s.tunnel===!0)o=!0;else if(s.tunnel===!1)o=!1,e.tunnel?.preference==="always"&&(u.set("tunnel",{...e.tunnel,preference:"no"},!0),await u.saveProjectConfig());else if(e.tunnel?.preference==="never")o=!1;else if(rr(e))o=!0;else{let{tunnelChoice:d}=await Pi.default.prompt([{type:"list",name:"tunnelChoice",message:"Enable Sinch tunnel for external access?",choices:[{name:"Yes - Enable tunnel this time",value:"yes"},{name:"No - Local only this time",value:"no"},{name:"Always - Enable tunnel and remember preference",value:"always"},{name:"Never - Don't enable tunnel and remember preference",value:"never"}],default:"no"}]);d==="yes"?o=!0:d==="no"?o=!1:d==="always"?(o=!0,u.set("tunnel",{...e.tunnel,preference:"always"},!0),await u.saveProjectConfig()):d==="never"&&(o=!1,u.set("tunnel",{...e.tunnel,preference:"never"},!0),await u.saveProjectConfig())}await tr(o,i);let r={...process.env,PORT:s.port,NODE_ENV:"development",SINCH_FUNCTIONS_LOCAL:"true",SINCH_TUNNEL:o?"true":"false"};e.variables&&Object.entries(e.variables).forEach(([d,f])=>{r[d]=f});try{let d=await u.getApplicationCredentials(e.voiceAppKey);d?(r.SINCH_APPLICATION_KEY=d.applicationKey,r.SINCH_APPLICATION_SECRET=d.applicationSecret,t.debug("\u2705 Injected application credentials for voice operations")):t.debug("\u26A0\uFE0F No application credentials found - voice features may not work")}catch(d){t.debug(`\u26A0\uFE0F Could not load application credentials: ${d.message}`)}t.info("\u{1F680} Starting local server...");let a=null,l=!1;function p(){if(a&&a.kill(),i==="csharp"){let d=["watch","run","--no-launch-profile"];n&&d.push("--project",n),s.port&&d.push("--urls",`http://localhost:${s.port}`),r.ASPNETCORE_ENVIRONMENT="Development",r.ASPNETCORE_URLS=`http://localhost:${s.port}`,a=(0,mn.spawn)("dotnet",d,{env:r,stdio:"inherit",cwd:process.cwd()})}else a=(0,mn.spawn)("npm",["run","dev"],{env:r,stdio:"inherit",cwd:process.cwd(),shell:!0});a.on("spawn",async()=>{if(!l){l=!0,t.newline(),t.success(`\u2705 Server running on http://localhost:${s.port}`),s.debug&&(t.newline(),i==="csharp"?ar():ir()),t.newline(),t.info("\u{1F4A1} Development commands:"),t.info(` \u2022 Test function: ${Ct.default.cyan(`curl http://localhost:${s.port}`)}`),t.info(` \u2022 View in browser: ${Ct.default.cyan(`http://localhost:${s.port}`)}`),t.info(` \u2022 Stop server: ${Ct.default.gray("Ctrl+C")}`);let d=i==="csharp"?"dotnet watch":"nodemon";t.info(` \u2022 File watching: ${Ct.default.green(`enabled (via ${d})`)}`)}}),a.on("error",d=>{t.error(`Server error: ${d.message}`)}),a.on("exit",(d,f)=>{f!=="SIGTERM"&&f!=="SIGKILL"&&t.error(`Server exited with code ${d}`)})}p(),process.on("SIGINT",()=>{t.newline(),t.info("\u{1F534} Stopping development server..."),a&&a.kill("SIGTERM"),process.exit(0)}),await new Promise(()=>{})}async function ir(){try{let s=await it("code",".vscode"),e=await it("cursor",".cursor"),n=await it("webstorm",".idea");if(s||e){let i=s?"VS Code":"Cursor",o=".vscode";if(t.info(`\u{1F41B} ${i} detected! Debug setup:`),await or(o))t.info(" 1. \u2705 Created .vscode/launch.json for you");else{let a=fe.default.join(process.cwd(),o,"launch.json");await U.default.pathExists(a)?t.info(" 1. \u2705 Found existing .vscode/launch.json"):t.info(" 1. \u26A0\uFE0F Could not create .vscode/launch.json")}t.info(" 2. \u{1F50D} Press F5 to attach debugger"),t.info(" 3. \u{1F534} Set breakpoints in your function.js"),t.info(" 4. \u{1F4DE} Test your function to hit breakpoints")}else n?(t.info("\u{1F41B} WebStorm detected! Debug setup:"),t.info(" 1. \u{1F50D} Run \u2192 Attach to Node.js/Chrome \u2192 localhost:9229"),t.info(" 2. \u{1F534} Set breakpoints in your function.js")):(t.info("\u{1F41B} Manual debug setup:"),t.info(' \u2022 VS Code/Cursor: Open "Run and Debug" \u2192 "Attach to Node.js Process"'),t.info(' \u2022 Chrome DevTools: Visit chrome://inspect \u2192 Click "inspect"'),t.info(" \u2022 Manual: Connect debugger to ws://localhost:9229"))}catch{t.info("\u{1F41B} Debug instructions:"),t.info(" \u2022 Connect your debugger to ws://localhost:9229"),t.info(" \u2022 Set breakpoints and test your function")}}async function it(s,e){try{if(s==="code"&&sr())return!0;let{spawn:n}=require("child_process"),i=await new Promise(r=>{let a=n(s,["--version"],{stdio:"pipe"});a.on("close",l=>r(l===0)),a.on("error",()=>r(!1))}),o=e?await U.default.pathExists(e):!1;return i||o}catch{return!1}}function sr(){return process.env.TERM_PROGRAM==="vscode"||!!process.env.VSCODE_IPC_HOOK||!!process.env.VSCODE_PID}async function or(s=".vscode"){try{let e=fe.default.join(process.cwd(),s),n=fe.default.join(e,"launch.json");if(await U.default.pathExists(n))return!1;await U.default.ensureDir(e);let i={version:"0.2.0",configurations:[{name:"Attach to Sinch Function",type:"node",request:"attach",port:9229,localRoot:"${workspaceFolder}",remoteRoot:"${workspaceFolder}",skipFiles:["<node_internals>/**","node_modules/**"]}]};return await U.default.writeJson(n,i,{spaces:2}),!!await U.default.pathExists(n)}catch{return!1}}function rr(s){return s.tunnel?s.tunnel.preference==="always":!1}async function ar(){try{let s=await it("code",".vscode"),e=await it("devenv"),n=await it("rider",".idea");s?(t.info("\u{1F41B} VS Code detected! Debug setup:"),await cr(".vscode")?t.info(" 1. \u2705 Created .vscode/launch.json for C#"):t.info(" 1. \u2705 Found existing .vscode/launch.json"),t.info(" 2. \u{1F50D} Press F5 to attach debugger"),t.info(" 3. \u{1F534} Set breakpoints in your Function.cs"),t.info(" 4. \u{1F4DE} Test your function to hit breakpoints")):e?(t.info("\u{1F41B} Visual Studio detected! Debug setup:"),t.info(" 1. \u{1F50D} Debug \u2192 Attach to Process \u2192 dotnet.exe"),t.info(" 2. \u{1F534} Set breakpoints in your Function.cs"),t.info(" 3. \u{1F4DE} Test your function to hit breakpoints")):n?(t.info("\u{1F41B} JetBrains Rider detected! Debug setup:"),t.info(" 1. \u{1F50D} Run \u2192 Attach to Process \u2192 dotnet"),t.info(" 2. \u{1F534} Set breakpoints in your Function.cs")):(t.info("\u{1F41B} C# Debug setup:"),t.info(" \u2022 Visual Studio: Debug \u2192 Attach to Process \u2192 dotnet.exe"),t.info(" \u2022 VS Code: Install C# extension, then F5 to debug"),t.info(" \u2022 Rider: Run \u2192 Attach to Process"))}catch{t.info("\u{1F41B} C# Debug instructions:"),t.info(" \u2022 Attach your debugger to the dotnet process"),t.info(" \u2022 Set breakpoints in Function.cs")}}async function cr(s=".vscode"){try{let e=fe.default.join(process.cwd(),s),n=fe.default.join(e,"launch.json");if(await U.default.pathExists(n))return!1;await U.default.ensureDir(e);let i={version:"0.2.0",configurations:[{name:".NET Core Launch (web)",type:"coreclr",request:"launch",preLaunchTask:"build",program:"${workspaceFolder}/bin/Debug/net8.0/Function.dll",args:[],cwd:"${workspaceFolder}",stopAtEntry:!1,serverReadyAction:{action:"openExternally",pattern:"\\bNow listening on:\\s+(https?://\\S+)"},env:{ASPNETCORE_ENVIRONMENT:"Development"},sourceFileMap:{"/Views":"${workspaceFolder}/Views"}},{name:".NET Core Attach",type:"coreclr",request:"attach"}]};await U.default.writeJson(n,i,{spaces:2});let o=fe.default.join(e,"tasks.json");if(!await U.default.pathExists(o)){let r={version:"2.0.0",tasks:[{label:"build",command:"dotnet",type:"process",args:["build","${workspaceFolder}/Function.csproj","/property:GenerateFullPaths=true","/consoleloggerparameters:NoSummary"],problemMatcher:"$msCompile"}]};await U.default.writeJson(o,r,{spaces:2})}return await U.default.pathExists(n)}catch{return!1}}Ei.exports=Ai});var Oi=R((uc,Ni)=>{"use strict";var ee=h(require("chalk")),Di=require("commander");z();k();A();E();var ji=new Di.Command("status");ji.description("Show function status and details").argument("[function-id]","Function ID to check (optional if sinch.json exists)").option("-f, --follow","Watch status changes in real-time").option("--json","Output raw JSON").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig()),i=s;if(!i){if(!u.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");if(i=u.getProjectConfig()?.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}e.follow?await dr(n,i):await lr(n,i,e)}catch(n){c.stop(),t.error(`Failed to get function status: ${n.message}`),process.exit(1)}});async function lr(s,e,n){c.start("\u{1F4E1} Loading function status...");try{let i=await s.getFunction(e),o=await s.getFunctionStatus(e);if(c.stop(),n.json){console.log(JSON.stringify({function:i,deployment:o},null,2));return}let r=i,a=o.status,l=o.error;t.newline(),t.title(`Function Status: ${r.name}`),t.newline(),t.info("\u{1F4CB} Function Details:"),t.info(` ID: ${ee.default.gray(r.id)}`),t.info(` Name: ${ee.default.cyan(r.name)}`),t.info(` Runtime: ${ee.default.yellow(r.runtime)}`),t.info(` Deployment Status: ${Ri(a)}`),r.created&&t.info(` Created: ${new Date(r.created).toLocaleString()}`),r.updated&&t.info(` Updated: ${new Date(r.updated).toLocaleString()}`),r.url&&t.info(` URL: ${ee.default.blue(r.url)}`),a==="Failed"&&l&&(t.newline(),t.error("Deployment Error:"),t.error(` ${l}`)),t.newline(),t.info("\u{1F4A1} Commands:"),t.info(` \u2022 View logs: ${ee.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Redeploy: ${ee.default.cyan("sinch functions deploy")}`),t.info(` \u2022 Delete: ${ee.default.cyan(`sinch functions delete ${e}`)}`)}catch(i){throw c.stop(),i}}async function dr(s,e){t.info("\u{1F440} Watching deployment status (press Ctrl+C to stop)..."),t.newline();let n=null,i=setInterval(async()=>{try{let o=await s.getFunctionStatus(e),r=o.status;if(r!==n){let a=new Date().toLocaleTimeString();if(t.info(`[${a}] Status: ${Ri(r)}`),n=r,r==="Running"){t.success("Function deployment is now running!");try{let l=await s.getFunction(e);l.url&&t.info(`URL: ${ee.default.blue(l.url)}`)}catch{}}else r==="Failed"&&(t.error("Function deployment failed!"),o.error&&t.error(`Error: ${o.error}`),clearInterval(i))}}catch(o){t.error(`Error checking status: ${o.message}`)}},3e3);process.on("SIGINT",()=>{clearInterval(i),t.newline(),t.info("Stopped watching function status"),process.exit(0)})}function Ri(s){return{Running:ee.default.green("\u2705 Running"),Failed:ee.default.red("\u274C Failed"),Pending:ee.default.yellow("\u23F3 Pending"),Building:ee.default.blue("\u{1F528} Building")}[s]||ee.default.gray(s)}Ni.exports=ji});var Bi=R((yc,Ji)=>{"use strict";var Be=h(require("chalk")),Li=require("commander");z();k();A();E();var hn=require("child_process"),bt=h(require("fs")),St=h(require("os")),vt=h(require("path")),yn=new Li.Command("logs");yn.description("View function logs").argument("[function-id]","Function ID to get logs for (optional if sinch.json exists)").option("-f, --follow","Follow log output in real-time").option("-n, --lines <number>","Number of historical lines to show","50").option("--level <level>","Filter by log level (debug, info, warning, error)").option("--search <text>","Search for text in log messages").option("--since <duration>","Show logs since duration (e.g., 1h, 30m, 5s)").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig()),i=s;if(!i){if(!u.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let r=u.getProjectConfig();if(!r)throw new Error("No project configuration found");if(i=r.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}c.start("Loading function details...");let o=await n.getFunction(i);c.stop(),t.info(`\u{1F4CB} Logs for function: ${Be.default.cyan(o.name)} (${ur(o.status)})`),t.newline(),e.follow?await _i(n,i,o.name,e):await vr(n,i,e)}catch(n){c.stop(),t.error(`Failed to get logs: ${n.message}`),process.exit(1)}});yn.command("stream").description("Stream function logs in real-time").argument("[function-id]","Function ID to stream logs for (optional if sinch.json exists)").option("--level <level>","Filter by log level (debug, info, warning, error)").option("--search <text>","Search for text in log messages").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig()),i=s;if(!i){if(!u.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let r=u.getProjectConfig();if(!r)throw new Error("No project configuration found");if(i=r.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}c.start("Connecting to log stream...");let o=await pr(n,i);c.stop(),await _i(n,i,o.name,{...e,follow:!0})}catch(n){c.stop(),t.error(`Failed to stream logs: ${n.message}`),process.exit(1)}});async function pr(s,e){return await s.getFunction(e)}async function _i(s,e,n,i){let o=s.baseUrl.replace(/\/+$/,""),r=s.projectId,a=`${o}/v1/projects/${r}/functions/${e}/logs/stream`,l=s.credentials,p=[],d=qi(p,"STREAMING",n),f={Accept:"text/event-stream","Cache-Control":"no-cache"};if(l)try{let w=await l.retrieve();if(w&&w.keyId&&w.keySecret){let y=Buffer.from(`${w.keyId}:${w.keySecret}`).toString("base64");f.Authorization=`Basic ${y}`}}catch(w){t.debug("Failed to add authentication:",w)}let g=new AbortController;try{let w=await fetch(a,{method:"GET",headers:f,signal:g.signal});if(!w.ok)throw new Error(`SSE connection failed: ${w.status} ${w.statusText}`);if(!w.body)throw new Error("Response body is null");Ti(d.statusBar,"CONNECTED",n),d.screen.render();let y=w.body.getReader(),v=new TextDecoder,$="";(async()=>{try{for(;;){let{done:D,value:C}=await y.read();if(D)break;$+=v.decode(C,{stream:!0});let S=$.split(`
61
+ `);$=S.pop()||"";for(let b of S)if(!b.startsWith("event:")&&b.startsWith("data:")){let I=b.substring(5).trim();if(I)try{let _=JSON.parse(I);_.type==="request"&&_.request&&(p.push(_.request),Ui(d.table,_.request,p),d.table.focus(),d.screen.render())}catch{}}}}catch(D){D.name!=="AbortError"&&(Ti(d.statusBar,"RECONNECTING",n),d.screen.render())}})(),d.screen.key(["q","C-c"],()=>{g.abort(),process.exit(0)}),await new Promise(()=>{})}catch(w){g.abort(),t.error(`\u274C Streaming failed: ${w.message}`),process.exit(1)}}function ur(s){return{Running:Be.default.green("\u2705 Running"),Failed:Be.default.red("\u274C Failed"),Pending:Be.default.yellow("\u23F3 Pending"),Building:Be.default.blue("\u{1F528} Building")}[s]||Be.default.gray(s)}var Ke=[];function Ui(s,e,n){let i=new Date(e.startTime),o=i.getFullYear()+"-"+String(i.getMonth()+1).padStart(2,"0")+"-"+String(i.getDate()).padStart(2,"0")+" "+String(i.getHours()).padStart(2,"0")+":"+String(i.getMinutes()).padStart(2,"0")+":"+String(i.getSeconds()).padStart(2,"0"),r=Sr(e),a=`${e.executionTimeMs}ms`,l=e.statusCode.toString(),p=process.stdout.columns||120,f=Math.max(30,p-35),g=e.url.length>f?e.url.substring(0,f-2)+"..":e.url;Ke.push([o,r,a,l,g]),Ke.length>100&&(Ke=Ke.slice(-100),n&&n.length>100&&n.splice(0,n.length-100));let w=[["Time","Callback","Duration","Status","Path"],...Ke];s.setData(w)}function fr(s,e,n,i,o){try{let r=require("blessed");t.debug(`Showing request details for ${s.httpMethod} ${s.url}`);let a=r.box({parent:e,top:0,left:0,width:"100%",height:"100%",border:{type:"line"},style:{border:{fg:"cyan"},bg:"black",fg:"white"},scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,label:" Request Details "}),l=r.box({parent:a,top:1,left:2,width:"100%-4",height:1,content:"{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J/1] JSON [C/2] cURL{/}",tags:!0,style:{bg:"blue",fg:"white"}});r.box({parent:a,top:2,left:2,width:"100%-4",height:1,content:`{bold}{cyan-fg}${s.httpMethod}{/} {blue-fg}${s.url}{/} - {${Cr(s.statusCode)}}${s.statusCode}{/} - {yellow-fg}${s.executionTimeMs}ms{/} - {magenta-fg}${s.memoryUsedMB||0}MB{/}`,tags:!0,style:{bg:"black"}});let p=r.box({parent:a,top:4,left:2,width:"100%-4",height:"100%-5",scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,content:gr(s)});p.focus(),e.render();let d=!0,f=()=>{d&&(d=!1,a.destroy(),n.focus(),e.render())};e.key(["escape","q"],()=>{d&&f()}),e.key(["up","k"],()=>{d&&(p.scroll(-1),e.render())}),e.key(["down","j"],()=>{d&&(p.scroll(1),e.render())}),e.on("keypress",(g,w)=>{d&&t.debug(`Key pressed: ch="${g}" key=${JSON.stringify(w)}`)}),e.key(["J","j"],()=>{d&&(t.debug("J/j key pressed - attempting JSON copy"),l.setContent("{black-bg}{yellow-fg} J KEY PRESSED - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let g=JSON.stringify(s,null,2);t.debug(`JSON content length: ${g.length}`),t.debug("Attempting native clipboard copy"),_t(g).then(()=>{l.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{t.debug(`Native clipboard failed: ${w.message}`);let y=vt.default.join(St.default.tmpdir(),`sinch-request-${Date.now()}.json`);bt.default.writeFileSync(y,g),l.setContent(`{yellow-fg}\u2713 JSON saved to: ${y}{/}`),t.debug(`Saved to temp file: ${y}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(g){t.debug(`JSON copy error: ${g.message}`),l.setContent(`{red-fg}\u2717 Copy failed: ${g.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["C","c"],()=>{d&&(t.debug("C/c key pressed - attempting cURL copy"),l.setContent("{black-bg}{yellow-fg} C KEY PRESSED - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let g=Fi(s);t.debug("Attempting native clipboard copy for cURL"),_t(g).then(()=>{l.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded for cURL"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{t.debug(`Native clipboard failed for cURL: ${w.message}`);let y=vt.default.join(St.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);bt.default.writeFileSync(y,g),l.setContent(`{yellow-fg}\u2713 cURL saved to: ${y}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(g){t.debug(`cURL copy error: ${g.message}`),l.setContent(`{red-fg}\u2717 Copy failed: ${g.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["1"],()=>{d&&(t.debug("1 key pressed - copying JSON (alternative binding)"),l.setContent("{black-bg}{yellow-fg} 1 KEY - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let g=JSON.stringify(s,null,2);_t(g).then(()=>{l.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{let y=vt.default.join(St.default.tmpdir(),`sinch-request-${Date.now()}.json`);bt.default.writeFileSync(y,g),l.setContent(`{yellow-fg}\u2713 JSON saved to: ${y}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(g){l.setContent(`{red-fg}\u2717 Copy failed: ${g.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["2"],()=>{d&&(t.debug("2 key pressed - copying cURL (alternative binding)"),l.setContent("{black-bg}{yellow-fg} 2 KEY - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let g=Fi(s);_t(g).then(()=>{l.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(w=>{let y=vt.default.join(St.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);bt.default.writeFileSync(y,g),l.setContent(`{yellow-fg}\u2713 cURL saved to: ${y}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(g){l.setContent(`{red-fg}\u2717 Copy failed: ${g.message}{/}`),e.render(),setTimeout(()=>{d&&(l.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))})}catch(r){t.debug(`Error in showBlessedZoomedRequest: ${r.message}`)}}function gr(s){let e="";return e+=`
63
62
  `,e+=mr(s),e+=`
64
- `,e+=hr(s),e}function gr(s){let e="",n=process.stdout.columns-6;e+="{bold}{green-fg}\u250C\u2500 REQUEST "+"\u2500".repeat(Math.max(0,n-10))+`\u2510{/}
65
- `;let i=Cr(s);if(i&&(e+=`{green-fg}\u2502{/} {bold}Call ID:{/} {cyan-fg}${i}{/}
63
+ `,e+=hr(s),e+=`
64
+ `,e+=yr(s),e}function mr(s){let e="",n=process.stdout.columns-6;e+="{bold}{green-fg}\u250C\u2500 REQUEST "+"\u2500".repeat(Math.max(0,n-10))+`\u2510{/}
65
+ `;let i=br(s);if(i&&(e+=`{green-fg}\u2502{/} {bold}Call ID:{/} {cyan-fg}${i}{/}
66
66
  `),s.headers){e+=`{green-fg}\u2502{/} {bold}Headers:{/}
67
67
  `;try{let o=typeof s.headers=="string"?JSON.parse(s.headers):s.headers;Object.entries(o).forEach(([r,a])=>{let l=` ${r}: ${a}`;e+=ge(l,n-2,"{green-fg}\u2502{/} ")})}catch{e+=ge(` ${s.headers}`,n-2,"{green-fg}\u2502{/} ")}}if(s.requestBody){e+=`{green-fg}\u2502{/} {bold}Body:{/}
68
68
  `;try{let o=JSON.parse(s.requestBody);JSON.stringify(o,null,2).split(`
69
69
  `).forEach(a=>{e+=ge(a,n-2,"{green-fg}\u2502{/} ")})}catch{e+=ge(s.requestBody,n-2,"{green-fg}\u2502{/} ")}}return e+="{green-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
70
- `,e}function mr(s){let e="",n=process.stdout.columns-6;if(e+="{bold}{blue-fg}\u250C\u2500 RESPONSE "+"\u2500".repeat(Math.max(0,n-11))+`\u2510{/}
70
+ `,e}function hr(s){let e="",n=process.stdout.columns-6;if(e+="{bold}{blue-fg}\u250C\u2500 RESPONSE "+"\u2500".repeat(Math.max(0,n-11))+`\u2510{/}
71
71
  `,s.responseHeaders){e+=`{blue-fg}\u2502{/} {bold}Headers:{/}
72
72
  `;try{let i=typeof s.responseHeaders=="string"?JSON.parse(s.responseHeaders):s.responseHeaders;Object.entries(i).forEach(([o,r])=>{let a=` ${o}: ${r}`;e+=ge(a,n-2,"{blue-fg}\u2502{/} ")})}catch{e+=ge(` ${s.responseHeaders}`,n-2,"{blue-fg}\u2502{/} ")}}if(s.responseBody){e+=`{blue-fg}\u2502{/} {bold}Body:{/}
73
73
  `;try{let i=JSON.parse(s.responseBody);JSON.stringify(i,null,2).split(`
74
74
  `).forEach(r=>{e+=ge(r,n-2,"{blue-fg}\u2502{/} ")})}catch{e+=ge(s.responseBody,n-2,"{blue-fg}\u2502{/} ")}}return s.errorMessage&&(e+=`{blue-fg}\u2502{/} {bold}{red-fg}Error:{/}
75
75
  `,e+=ge(s.errorMessage,n-2,"{blue-fg}\u2502{/} ")),e+="{blue-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
76
- `,e}function hr(s){let e="",n=process.stdout.columns-6;return e+="{bold}{magenta-fg}\u250C\u2500 CONSOLE LOGS "+"\u2500".repeat(Math.max(0,n-15))+`\u2510{/}
77
- `,s.logs&&s.logs.length>0?s.logs.forEach((i,o)=>{let r=new Date(i.timestamp).toLocaleTimeString(),a=i.level.toUpperCase().padEnd(5),l=yr(i.level),p=`${r} [${a}] ${i.message}`;e+=ge(p,n-2,"{magenta-fg}\u2502{/} ",l)}):e+=`{magenta-fg}\u2502{/} {gray-fg}No console logs for this request{/}
76
+ `,e}function yr(s){let e="",n=process.stdout.columns-6;return e+="{bold}{magenta-fg}\u250C\u2500 CONSOLE LOGS "+"\u2500".repeat(Math.max(0,n-15))+`\u2510{/}
77
+ `,s.logs&&s.logs.length>0?s.logs.forEach((i,o)=>{let r=new Date(i.timestamp).toLocaleTimeString(),a=i.level.toUpperCase().padEnd(5),l=wr(i.level),p=`${r} [${a}] ${i.message}`;e+=ge(p,n-2,"{magenta-fg}\u2502{/} ",l)}):e+=`{magenta-fg}\u2502{/} {gray-fg}No console logs for this request{/}
78
78
  `,e+="{magenta-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
79
79
  `,e}function ge(s,e,n,i=""){if(!s)return"";let o="";return s.split(`
80
80
  `).forEach(a=>{if(a.length<=e)o+=`${n}${i}${a}{/}
81
81
  `;else{let l=a,p=!0;for(;l.length>e;){let d=e-(p?0:4),f=l.substring(0,d);o+=`${n}${p?"":" "}${i}${f}{/}
82
82
  `,l=l.substring(d),p=!1}l.length>0&&(o+=`${n}${p?"":" "}${i}${l}{/}
83
- `)}}),o}function yr(s){switch(s.toLowerCase()){case"debug":return"gray-fg";case"info":return"blue-fg";case"warning":return"yellow-fg";case"error":return"red-fg";default:return"white-fg"}}function wr(s){return s>=200&&s<300?"green-fg":s>=300&&s<400?"yellow-fg":s>=400&&s<500?"red-fg":s>=500?"red-fg}{bold":"white-fg"}function Cr(s){try{if(s.requestBody){let e=JSON.parse(s.requestBody);return e.callId||e.callid||e.call_id||null}}catch{}return null}function br(s){try{let e="";if(s.requestBody){let n=JSON.parse(s.requestBody);if(n.event)e=n.event.toLowerCase();else{let i=s.url.split("/").filter(o=>o);e=i[i.length-1]||""}return e||""}}catch{}return""}async function Sr(s,e,n){try{c.start(`Loading ${n.lines} recent log entries...`);let i={limit:parseInt(n.lines||"50"),level:n.level,search:n.search};if(n.since){let a=vr(n.since);a&&(i.startTime=a.toISOString())}let o=await s.getFunctionLogs(e,i);if(c.stop(),t.debug("Historical API response:",{totalRequests:o.requests?.length||0,firstRequest:o.requests?.[0]||"No requests",responseKeys:Object.keys(o)}),!o.requests||o.requests.length===0){t.info("\u{1F4DD} No logs found"),t.info("\u{1F4A1} Logs will appear here after function receives requests");return}let r=o.requests;t.debug("Historical requests:",{totalRequests:r.length,firstRequest:r[0]||"No requests",requestTimestamps:r.slice(0,3).map(a=>a.startTime)}),await $r(r,"HISTORICAL","Function")}catch(i){throw c.stop(),i}}function vr(s){if(!s)return null;let e=s.match(/^(\d+)([smhd])$/);if(!e)return null;let n=parseInt(e[1]),i=e[2],o=new Date;switch(i){case"s":return new Date(o.getTime()-n*1e3);case"m":return new Date(o.getTime()-n*60*1e3);case"h":return new Date(o.getTime()-n*60*60*1e3);case"d":return new Date(o.getTime()-n*24*60*60*1e3);default:return null}}async function $r(s,e,n){let i=qi(s,e,n);s.forEach(o=>{Ui(i.table,o,s)}),i.screen.render(),await new Promise(()=>{})}function qi(s,e,n){let i=require("blessed");process.stdout.write("\x1Bc"),Ke=[];let o=i.screen({smartCSR:!0,title:`Sinch Functions - ${n} Logs`,fullUnicode:!0}),r=i.box({parent:o,top:0,left:0,width:"100%",height:1,content:Mi(e,n),tags:!0,style:{bg:"black"}}),a=i.listtable({parent:o,top:1,left:0,width:"100%",height:"100%-1",border:{type:"line",fg:"blue"},style:{header:{fg:"white",bg:"blue",bold:!0},cell:{fg:"white"},selected:{bg:"blue",fg:"white",bold:!0}},keys:!0,vi:!0,mouse:!0,interactive:!0,label:`${n} Logs (q to quit)`,align:"left",pad:1}),l=["Time","Callback","Duration","Status","Path"];a.setData([l]),a.focus(),o.key(["q","C-c"],()=>{process.exit(0)});let p=()=>{try{let d=a.selected||0,f=d-1;if(f>=0&&f<s.length&&s[f])t.debug(`Opening request details for index ${f}`),ur(s[f],o,a,r,n);else{let g=`Selected: ${d}, DataIndex: ${f}, Requests: ${s.length}, TableData: ${Ke.length}`;t.debug(`Selection out of bounds: ${g}`)}}catch(d){t.debug(`Error in request selection: ${d.message}`)}};return o.key(["enter"],p),a.on("select",(d,f)=>{p()}),o.on("wheelup",()=>{a.focused&&(a.scroll(-1),o.render())}),o.on("wheeldown",()=>{a.focused&&(a.scroll(1),o.render())}),{screen:o,table:a,statusBar:r}}function Mi(s,e){switch(s){case"STREAMING":return"{blue-fg}\u{1F534} STREAMING: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"CONNECTED":return"{green-fg}\u2705 CONNECTED: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"RECONNECTING":return"{yellow-fg}\u26A0\uFE0F RECONNECTING: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"HISTORICAL":return"{cyan-fg}\u{1F4DC} HISTORICAL: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";default:return"{gray-fg}"+e+" | \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}"}}function Ti(s,e,n){s.setContent(Mi(e,n))}function _t(s){return new Promise((e,n)=>{let i,o;process.platform==="win32"?(i="clip",o=[]):process.platform==="darwin"?(i="pbcopy",o=[]):(i="xclip",o=["-selection","clipboard"]),t.debug(`Using clipboard command: ${i} with args:`,o);let r=(0,hn.spawn)(i,o,{stdio:["pipe","ignore","pipe"]}),a="";r.stderr.on("data",l=>{a+=l.toString()}),r.on("error",l=>{if(t.debug(`Clipboard process error: ${l.message}`),process.platform==="linux"&&i==="xclip"){t.debug("Trying xsel as fallback");let p=(0,hn.spawn)("xsel",["--clipboard","--input"],{stdio:["pipe","ignore","pipe"]});p.on("error",d=>{n(new Error(`No clipboard utility found: ${l.message} / ${d.message}`))}),p.on("close",d=>{d===0?e():n(new Error(`xsel failed with code ${d}`))}),p.stdin&&(p.stdin.write(s),p.stdin.end());return}n(l)}),r.on("close",l=>{l===0?(t.debug("Clipboard copy successful"),e()):(t.debug(`Clipboard process failed with code ${l}, error: ${a}`),n(new Error(`Clipboard command failed with code ${l}: ${a}`)))}),r.stdin&&(r.stdin.write(s),r.stdin.end())})}function Fi(s){let e=process.platform==="win32",n=`curl -X ${s.httpMethod}`,i={};if(s.headers)try{i=typeof s.headers=="string"?JSON.parse(s.headers):s.headers}catch{}let o=s.url;if(o&&!o.startsWith("http")){let r=i.host||i.Host;r&&(o=`${r.includes("localhost")||r.includes("127.0.0.1")?"http":"https"}://${r}${o.startsWith("/")?o:"/"+o}`)}if(n+=` "${o}"`,Object.entries(i).forEach(([r,a])=>{let l=["content-length","connection","user-agent"];s.url.startsWith("http")||l.push("host"),l.includes(r.toLowerCase())||(e?n+=` -H "${r}: ${a}"`:n+=` \\
83
+ `)}}),o}function wr(s){switch(s.toLowerCase()){case"debug":return"gray-fg";case"info":return"blue-fg";case"warning":return"yellow-fg";case"error":return"red-fg";default:return"white-fg"}}function Cr(s){return s>=200&&s<300?"green-fg":s>=300&&s<400?"yellow-fg":s>=400&&s<500?"red-fg":s>=500?"red-fg}{bold":"white-fg"}function br(s){try{if(s.requestBody){let e=JSON.parse(s.requestBody);return e.callId||e.callid||e.call_id||null}}catch{}return null}function Sr(s){try{let e="";if(s.requestBody){let n=JSON.parse(s.requestBody);if(n.event)e=n.event.toLowerCase();else{let i=s.url.split("/").filter(o=>o);e=i[i.length-1]||""}return e||""}}catch{}return""}async function vr(s,e,n){try{c.start(`Loading ${n.lines} recent log entries...`);let i={limit:parseInt(n.lines||"50"),level:n.level,search:n.search};if(n.since){let a=$r(n.since);a&&(i.startTime=a.toISOString())}let o=await s.getFunctionLogs(e,i);if(c.stop(),t.debug("Historical API response:",{totalRequests:o.requests?.length||0,firstRequest:o.requests?.[0]||"No requests",responseKeys:Object.keys(o)}),!o.requests||o.requests.length===0){t.info("\u{1F4DD} No logs found"),t.info("\u{1F4A1} Logs will appear here after function receives requests");return}let r=o.requests;t.debug("Historical requests:",{totalRequests:r.length,firstRequest:r[0]||"No requests",requestTimestamps:r.slice(0,3).map(a=>a.startTime)}),await Ir(r,"HISTORICAL","Function")}catch(i){throw c.stop(),i}}function $r(s){if(!s)return null;let e=s.match(/^(\d+)([smhd])$/);if(!e)return null;let n=parseInt(e[1]),i=e[2],o=new Date;switch(i){case"s":return new Date(o.getTime()-n*1e3);case"m":return new Date(o.getTime()-n*60*1e3);case"h":return new Date(o.getTime()-n*60*60*1e3);case"d":return new Date(o.getTime()-n*24*60*60*1e3);default:return null}}async function Ir(s,e,n){let i=qi(s,e,n);s.forEach(o=>{Ui(i.table,o,s)}),i.screen.render(),await new Promise(()=>{})}function qi(s,e,n){let i=require("blessed");process.stdout.write("\x1Bc"),Ke=[];let o=i.screen({smartCSR:!0,title:`Sinch Functions - ${n} Logs`,fullUnicode:!0}),r=i.box({parent:o,top:0,left:0,width:"100%",height:1,content:Mi(e,n),tags:!0,style:{bg:"black"}}),a=i.listtable({parent:o,top:1,left:0,width:"100%",height:"100%-1",border:{type:"line",fg:"blue"},style:{header:{fg:"white",bg:"blue",bold:!0},cell:{fg:"white"},selected:{bg:"blue",fg:"white",bold:!0}},keys:!0,vi:!0,mouse:!0,interactive:!0,label:`${n} Logs (q to quit)`,align:"left",pad:1}),l=["Time","Callback","Duration","Status","Path"];a.setData([l]),a.focus(),o.key(["q","C-c"],()=>{process.exit(0)});let p=()=>{try{let d=a.selected||0,f=d-1;if(f>=0&&f<s.length&&s[f])t.debug(`Opening request details for index ${f}`),fr(s[f],o,a,r,n);else{let g=`Selected: ${d}, DataIndex: ${f}, Requests: ${s.length}, TableData: ${Ke.length}`;t.debug(`Selection out of bounds: ${g}`)}}catch(d){t.debug(`Error in request selection: ${d.message}`)}};return o.key(["enter"],p),a.on("select",(d,f)=>{p()}),o.on("wheelup",()=>{a.focused&&(a.scroll(-1),o.render())}),o.on("wheeldown",()=>{a.focused&&(a.scroll(1),o.render())}),{screen:o,table:a,statusBar:r}}function Mi(s,e){switch(s){case"STREAMING":return"{blue-fg}\u{1F534} STREAMING: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"CONNECTED":return"{green-fg}\u2705 CONNECTED: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"RECONNECTING":return"{yellow-fg}\u26A0\uFE0F RECONNECTING: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";case"HISTORICAL":return"{cyan-fg}\u{1F4DC} HISTORICAL: "+e+"{/} {gray-fg}| \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}";default:return"{gray-fg}"+e+" | \u2191\u2193/Wheel=scroll | Enter/Click=details | Q=quit{/}"}}function Ti(s,e,n){s.setContent(Mi(e,n))}function _t(s){return new Promise((e,n)=>{let i,o;process.platform==="win32"?(i="clip",o=[]):process.platform==="darwin"?(i="pbcopy",o=[]):(i="xclip",o=["-selection","clipboard"]),t.debug(`Using clipboard command: ${i} with args:`,o);let r=(0,hn.spawn)(i,o,{stdio:["pipe","ignore","pipe"]}),a="";r.stderr.on("data",l=>{a+=l.toString()}),r.on("error",l=>{if(t.debug(`Clipboard process error: ${l.message}`),process.platform==="linux"&&i==="xclip"){t.debug("Trying xsel as fallback");let p=(0,hn.spawn)("xsel",["--clipboard","--input"],{stdio:["pipe","ignore","pipe"]});p.on("error",d=>{n(new Error(`No clipboard utility found: ${l.message} / ${d.message}`))}),p.on("close",d=>{d===0?e():n(new Error(`xsel failed with code ${d}`))}),p.stdin&&(p.stdin.write(s),p.stdin.end());return}n(l)}),r.on("close",l=>{l===0?(t.debug("Clipboard copy successful"),e()):(t.debug(`Clipboard process failed with code ${l}, error: ${a}`),n(new Error(`Clipboard command failed with code ${l}: ${a}`)))}),r.stdin&&(r.stdin.write(s),r.stdin.end())})}function Fi(s){let e=process.platform==="win32",n=`curl -X ${s.httpMethod}`,i={};if(s.headers)try{i=typeof s.headers=="string"?JSON.parse(s.headers):s.headers}catch{}let o=s.url;if(o&&!o.startsWith("http")){let r=i.host||i.Host;r&&(o=`${r.includes("localhost")||r.includes("127.0.0.1")?"http":"https"}://${r}${o.startsWith("/")?o:"/"+o}`)}if(n+=` "${o}"`,Object.entries(i).forEach(([r,a])=>{let l=["content-length","connection","user-agent"];s.url.startsWith("http")||l.push("host"),l.includes(r.toLowerCase())||(e?n+=` -H "${r}: ${a}"`:n+=` \\
84
84
  -H "${r}: ${a}"`)}),s.requestBody&&["POST","PUT","PATCH"].includes(s.httpMethod)){try{let r=JSON.parse(s.requestBody),a=JSON.stringify(r);e?n+=` -d '${a.replace(/'/g,"\\'")}'`:n+=` \\
85
85
  -d '${JSON.stringify(r,null,2)}'`}catch{e?n+=` -d '${s.requestBody.replace(/'/g,"\\'")}'`:n+=` \\
86
86
  -d '${s.requestBody}'`}n.toLowerCase().includes("content-type")||(e?n+=' -H "Content-Type: application/json"':n+=` \\
87
87
  -H "Content-Type: application/json"`)}return e?n+=" -v":n+=` \\
88
- -v`,n}Ji.exports=yn});var Wi=R((Sc,zi)=>{"use strict";var ne=h(require("chalk")),Ki=h(require("inquirer")),Vi=require("commander");z();k();A();E();var Hi=new Vi.Command("delete");Hi.alias("del").description("Delete a function").argument("<function-id>","Function ID to delete").option("-f, --force","Skip confirmation").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig());c.start("Loading function details...");let i=await n.getFunction(s);if(c.stop(),t.newline(),t.info("\u{1F5D1}\uFE0F Function to delete:"),t.info(` Name: ${ne.default.cyan(i.name)}`),t.info(` ID: ${ne.default.gray(i.id)}`),t.info(` Runtime: ${ne.default.yellow(i.runtime)}`),t.info(` Status: ${Ir(i.status)}`),t.info(` Created: ${new Date(i.createdAt).toLocaleString()}`),i.containerAppUrl&&t.info(` URL: ${ne.default.blue(i.containerAppUrl)}`),!e.force){t.newline(),t.warn("\u26A0\uFE0F This action cannot be undone!");let{confirm:o}=await Ki.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete function '${i.name}'?`,default:!1}]);if(!o){t.info("Deletion cancelled");return}}c.start("Deleting function..."),await n.deleteFunction(s),c.succeed(`Function '${i.name}' deleted successfully`),u.isInProject()&&u.getProjectConfig()?.functionId===s&&(u.set("functionId",void 0,!0),await u.saveProjectConfig(),t.newline(),t.info("\u{1F4A1} Removed function ID from sinch.json"),t.info(" Deploy again with: sinch functions deploy")),t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 List remaining functions: ${ne.default.cyan("sinch functions list")}`),t.info(` \u2022 Deploy new function: ${ne.default.cyan("sinch functions deploy")}`)}catch(n){c.stop(),n.message.includes("404")||n.message.includes("not found")?(t.error(`Function '${s}' not found`),t.info("\u{1F4A1} List available functions with:"),t.info(` ${ne.default.cyan("sinch functions list")}`)):t.error(`Failed to delete function: ${n.message}`),process.exit(1)}});function Ir(s){return{Running:ne.default.green("\u2705 Running"),Failed:ne.default.red("\u274C Failed"),Pending:ne.default.yellow("\u23F3 Pending"),Building:ne.default.blue("\u{1F528} Building")}[s]||ne.default.gray(s)}zi.exports=Hi});var Zi=R((Ac,Yi)=>{"use strict";var Gi=require("commander"),wn=h(require("fs-extra")),Cn=h(require("path")),Ve=h(require("chalk"));k();A();E();un();z();var bn=new Gi.Command("docs");bn.description("Generate documentation for voice functions (saves to README.md)");bn.option("-f, --fresh","Force regeneration (skip cache)").option("-u, --update","Update documentation for deployed function via API").action(async s=>{try{await u.load(),s.update?await Pr():await kr(s)}catch(e){c.fail("\u274C Failed to generate documentation"),e.message.includes("No function file found")?t.error("No function file found. Make sure you're in a function directory with function.js, index.js, or handler.js"):e.message.includes("unauthorized")||e.message.includes("401")?t.error("Authentication failed. Run `sinch auth login` first."):e.message.includes("AI service")?t.error("AI documentation service unavailable. Please try again later."):e.message.includes("Function not found")||e.message.includes("404")?t.error("Function not found. Make sure the function is deployed first."):t.error(`Error: ${e.message}`),t.debug("Full error:",e),process.exit(1)}});async function kr(s){c.start("\u{1F916} Generating documentation...");let e=await dn();c.succeed("\u2705 Documentation generated!"),await pn(e,"README.md"),await Ar()}async function Pr(){let s=Cn.default.basename(process.cwd());c.start("\u{1F4D6} Reading local README.md...");let e=Cn.default.join(process.cwd(),"README.md");if(!await wn.default.pathExists(e))throw new Error("README.md not found. Run `sinch functions docs` first to generate documentation locally.");if(!(await wn.default.readFile(e,"utf8")).trim())throw new Error("README.md is empty. Run `sinch functions docs` first to generate documentation.");c.text="\u{1F50D} Finding deployed function...";let r=(await new T(u.getApiConfig()).listFunctions()).find(a=>a.name===s);if(!r)throw new Error(`Function '${s}' not found in project. Make sure it's deployed first.`);c.text="\u{1F4E4} Uploading documentation content...",t.info("Documentation content ready for update"),c.succeed("\u2705 Documentation updated!"),t.newline(),t.success(`\u{1F4C4} Documentation updated for deployed function: ${Ve.default.cyan(s)}`),t.info(""),t.info("\u2728 Your function documentation has been updated:"),t.info(` \u2022 Function ID: ${Ve.default.gray(r.id)}`),t.info(` \u2022 Source: ${Ve.default.gray("Local README.md")}`),t.info(` \u2022 Updated: ${Ve.default.gray(new Date().toLocaleString())}`),t.info(` \u2022 View in dashboard: ${Ve.default.cyan("Dashboard \u2192 Functions \u2192 "+s)}`),t.newline(),t.info("\u{1F4A1} The updated documentation is now available in the dashboard!")}async function Ar(){t.newline(),t.success(`\u{1F4C4} Documentation updated in: ${Ve.default.cyan("README.md")}`),t.info(""),t.info("\u2728 Your function documentation is ready:"),t.info(" \u2022 Review and edit the AI-generated content as needed"),t.info(" \u2022 Sinch-themed diagrams will render in markdown viewers"),t.info(" \u2022 File is ready for version control and deployment"),t.newline(),t.info("\u{1F4A1} Popular markdown viewers:"),t.info(" \u2022 VS Code (built-in)"),t.info(" \u2022 GitHub (drag & drop file)"),t.info(" \u2022 Typora, Mark Text, or any markdown app")}Yi.exports=bn});var ns=R((Rc,ts)=>{"use strict";var V=h(require("chalk")),Sn=h(require("inquirer")),Qi=require("commander"),de=h(require("fs-extra")),xe=h(require("path")),Xi=h(require("adm-zip"));z();k();A();E();var es=new Qi.Command("download");es.description("Download function source code").argument("[function-id]","Function ID to download (ULID format)").option("-o, --output <dir>","Output directory (default: ./functions/<function-name>)").option("--no-extract","Keep as ZIP file without extracting").option("--non-interactive","Skip interactive selection").option("-f, --force","Overwrite existing directory without prompting").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig()),i=s;if(!i&&!e.nonInteractive){let d=await Er(n);if(!d){t.info("Download cancelled");return}i=d}i||(t.error("Function ID required. Provide as argument or select interactively"),t.info(`Usage: ${V.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABCDE")}`),t.info(` or: ${V.default.cyan("sinch functions download")} (interactive selection)`),process.exit(1)),c.start("\u{1F4E1} Fetching function metadata...");let o=await n.getFunction(i);c.succeed("Function metadata loaded");let r=xe.join("functions",o.name),a=e.output||r,l=xe.resolve(a);if(await de.pathExists(l)){if(!e.force){let{overwrite:d}=await Sn.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${a}' already exists. Overwrite?`,default:!1}]);if(!d){t.info("Download cancelled");return}}c.start("\u{1F5D1}\uFE0F Removing existing directory..."),await de.remove(l),c.succeed("Existing directory removed")}c.start("\u{1F4E5} Downloading function source code...");let p=await n.downloadFunction(i);if(c.succeed("Source code downloaded"),e.extract!==!1){c.start("\u{1F4E6} Extracting files..."),await de.ensureDir(l);let d=new Xi.default(p),f=d.getEntries();d.extractAllTo(l,!0),c.succeed(`\u{1F4E6} Extracted ${f.length} files`);let g=xe.join(l,"sinch-metadata.json"),w={functionId:o.id,name:o.name,runtime:o.runtime,status:o.status,downloadedAt:new Date().toISOString(),url:o.containerAppUrl,configuration:o.configuration};await de.writeJson(g,w,{spaces:2}),t.newline(),t.success("\u2705 Function downloaded successfully!"),t.newline(),t.info(`\u{1F4C1} Location: ${V.default.cyan(a)}`),t.info(`\u{1F4CB} Files: ${f.length} files extracted`);let y=xe.join(l,"sinch.json");await de.pathExists(y)&&t.info("\u{1F527} Config: sinch.json found"),t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 Navigate: ${V.default.cyan(`cd ${a}`)}`),t.info(` \u2022 Run locally: ${V.default.cyan("sinch functions dev")}`),t.info(` \u2022 Deploy changes: ${V.default.cyan("sinch functions deploy")}`)}else{let d=`${o.name}.zip`,f=e.output?xe.resolve(e.output):xe.resolve(d);c.start(`\u{1F4BE} Saving as ${d}...`),await de.writeFile(f,p),c.succeed("ZIP file saved"),t.newline(),t.success("\u2705 Function downloaded as ZIP!"),t.info(`\u{1F4C1} File: ${V.default.cyan(f)}`),t.info(`\u{1F4E6} Size: ${(p.length/1024).toFixed(2)} KB`)}}catch(n){c.stop(),n.message.includes("404")||n.message.includes("not found")?(t.error(`Function not found with ID: ${s}`),t.info("\u{1F4A1} List available functions with:"),t.info(` ${V.default.cyan("sinch functions list")}`),t.info("\u{1F4A1} Or use interactive selection:"),t.info(` ${V.default.cyan("sinch functions download")}`)):t.error(`Failed to download function: ${n.message}`),process.exit(1)}});async function Er(s){try{c.start("\u{1F4CB} Loading functions...");let e=await s.listFunctions();if(c.stop(),!e.functions||e.functions.length===0)return t.warn("No functions found to download"),null;let n=e.functions.map(o=>({name:`${V.default.cyan(o.name.padEnd(20))} ${V.default.yellow(o.runtime.padEnd(8))} ${xr(o.status)}`,value:o.id,short:o.name}));t.newline();let{selectedFunction:i}=await Sn.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function to download:",choices:n,pageSize:15}]);return i}catch(e){throw c.stop(),e}}function xr(s){return{Running:V.default.green("\u2705 Running"),Failed:V.default.red("\u274C Failed"),Pending:V.default.yellow("\u23F3 Pending"),Building:V.default.blue("\u{1F528} Building")}[s]||V.default.gray(s)}ts.exports=es});var os=R((Nc,ss)=>{"use strict";var is=require("commander"),Dr=oi(),jr=di(),Rr=Ii(),Nr=xi(),Or=Oi(),Tr=Bi(),Fr=Wi(),Lr=Zi(),_r=ns(),pe=new is.Command("functions");pe.description("Manage Sinch Functions");pe.addCommand(Dr);pe.addCommand(jr);pe.addCommand(Rr);pe.addCommand(_r);pe.addCommand(Nr);pe.addCommand(Or);pe.addCommand(Tr);pe.addCommand(Fr);pe.addCommand(Lr);ss.exports=pe});var cs=R((_c,as)=>{"use strict";var rs=require("commander"),ie=h(require("chalk"));z();k();A();E();var me=new rs.Command("templates");me.description("Browse and manage function templates");me.command("list").alias("ls").description("List available templates").argument("[runtime]","Filter by runtime (node, csharp, python)").option("-c, --category <category>","Filter by category (voice, sms, verification)").option("-d, --detailed","Show detailed information").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig());c.start("Loading templates...");let i;if(s?i=await n.listRuntimeTemplates(s,e.category):i=await n.listAllTemplates(e.category),c.stop(),i.templates.length===0){t.info(`No templates found${s?` for ${s}`:""}${e.category?` in category ${e.category}`:""}`);return}let o=`Available Templates${s?` (${s})`:""}${e.category?` - ${e.category}`:""}`;if(t.title(o),e.detailed)i.templates.forEach((r,a)=>{a>0&&t.newline(),t.log(ie.default.bold.blue(`${r.name}`)),t.log(` Runtime: ${r.runtime}`),t.log(` Category: ${r.category}`),t.log(` Description: ${r.description}`),r.tags&&r.tags.length>0&&t.log(` Tags: ${r.tags.map(l=>ie.default.gray(l)).join(", ")}`),t.log(` Path: ${ie.default.gray(r.path)}`)});else{let r=i.templates.map(a=>[a.name,a.runtime,a.category,a.description.substring(0,50)+(a.description.length>50?"...":""),a.tags?a.tags.slice(0,2).join(", ")+(a.tags.length>2?"...":""):""]);t.table(["Name","Runtime","Category","Description","Tags"],r)}t.newline(),t.info(`Found ${i.templates.length} template${i.templates.length===1?"":"s"}`),t.info('Use "sinch templates show <runtime>/<template>" for details')}catch(n){c.stop(),t.error(`Failed to list templates: ${n.message}`),process.exit(1)}});me.command("show").description("Show detailed template information").argument("<template>",'Template name in format "runtime/template-name"').action(async s=>{try{await u.load();let e=new T(u.getApiConfig());if(!s.includes("/"))throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');let n=s.split("/"),i=n[0],o=n[1];if(!i||!o)throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');c.start(`Loading template details for ${s}...`);let r=await e.getTemplateDetails(i,o);c.stop(),t.title(`Template: ${r.name}`),t.newline(),t.log(ie.default.bold("Basic Information:")),t.log(` Runtime: ${r.runtime}`),t.log(` Category: ${r.category}`),t.log(` Description: ${r.description}`),r.tags&&r.tags.length>0&&t.log(` Tags: ${r.tags.map(a=>ie.default.blue(a)).join(", ")}`),r.variables&&Object.keys(r.variables).length>0&&(t.newline(),t.log(ie.default.bold("Template Variables:")),Object.entries(r.variables).forEach(([a,l])=>{t.log(` ${a}: ${ie.default.gray(l)}`)})),r.files&&r.files.length>0&&(t.newline(),t.log(ie.default.bold("Files:")),r.files.forEach(a=>{t.log(` ${ie.default.gray("\u2022")} ${a}`)})),r.readmeContent&&(t.newline(),t.log(ie.default.bold("README:")),r.readmeContent.split(`
88
+ -v`,n}Ji.exports=yn});var Wi=R((vc,zi)=>{"use strict";var ne=h(require("chalk")),Ki=h(require("inquirer")),Vi=require("commander");z();k();A();E();var Hi=new Vi.Command("delete");Hi.alias("del").description("Delete a function").argument("<function-id>","Function ID to delete").option("-f, --force","Skip confirmation").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig());c.start("Loading function details...");let i=await n.getFunction(s);if(c.stop(),t.newline(),t.info("\u{1F5D1}\uFE0F Function to delete:"),t.info(` Name: ${ne.default.cyan(i.name)}`),t.info(` ID: ${ne.default.gray(i.id)}`),t.info(` Runtime: ${ne.default.yellow(i.runtime)}`),t.info(` Status: ${kr(i.status)}`),t.info(` Created: ${new Date(i.createdAt).toLocaleString()}`),i.containerAppUrl&&t.info(` URL: ${ne.default.blue(i.containerAppUrl)}`),!e.force){t.newline(),t.warn("\u26A0\uFE0F This action cannot be undone!");let{confirm:o}=await Ki.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete function '${i.name}'?`,default:!1}]);if(!o){t.info("Deletion cancelled");return}}c.start("Deleting function..."),await n.deleteFunction(s),c.succeed(`Function '${i.name}' deleted successfully`),u.isInProject()&&u.getProjectConfig()?.functionId===s&&(u.set("functionId",void 0,!0),await u.saveProjectConfig(),t.newline(),t.info("\u{1F4A1} Removed function ID from sinch.json"),t.info(" Deploy again with: sinch functions deploy")),t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 List remaining functions: ${ne.default.cyan("sinch functions list")}`),t.info(` \u2022 Deploy new function: ${ne.default.cyan("sinch functions deploy")}`)}catch(n){c.stop(),n.message.includes("404")||n.message.includes("not found")?(t.error(`Function '${s}' not found`),t.info("\u{1F4A1} List available functions with:"),t.info(` ${ne.default.cyan("sinch functions list")}`)):t.error(`Failed to delete function: ${n.message}`),process.exit(1)}});function kr(s){return{Running:ne.default.green("\u2705 Running"),Failed:ne.default.red("\u274C Failed"),Pending:ne.default.yellow("\u23F3 Pending"),Building:ne.default.blue("\u{1F528} Building")}[s]||ne.default.gray(s)}zi.exports=Hi});var Zi=R((Ec,Yi)=>{"use strict";var Gi=require("commander"),wn=h(require("fs-extra")),Cn=h(require("path")),Ve=h(require("chalk"));k();A();E();un();z();var bn=new Gi.Command("docs");bn.description("Generate documentation for voice functions (saves to README.md)");bn.option("-f, --fresh","Force regeneration (skip cache)").option("-u, --update","Update documentation for deployed function via API").action(async s=>{try{await u.load(),s.update?await Ar():await Pr(s)}catch(e){c.fail("\u274C Failed to generate documentation"),e.message.includes("No function file found")?t.error("No function file found. Make sure you're in a function directory with function.js, index.js, or handler.js"):e.message.includes("unauthorized")||e.message.includes("401")?t.error("Authentication failed. Run `sinch auth login` first."):e.message.includes("AI service")?t.error("AI documentation service unavailable. Please try again later."):e.message.includes("Function not found")||e.message.includes("404")?t.error("Function not found. Make sure the function is deployed first."):t.error(`Error: ${e.message}`),t.debug("Full error:",e),process.exit(1)}});async function Pr(s){c.start("\u{1F916} Generating documentation...");let e=await dn();c.succeed("\u2705 Documentation generated!"),await pn(e,"README.md"),await Er()}async function Ar(){let s=Cn.default.basename(process.cwd());c.start("\u{1F4D6} Reading local README.md...");let e=Cn.default.join(process.cwd(),"README.md");if(!await wn.default.pathExists(e))throw new Error("README.md not found. Run `sinch functions docs` first to generate documentation locally.");if(!(await wn.default.readFile(e,"utf8")).trim())throw new Error("README.md is empty. Run `sinch functions docs` first to generate documentation.");c.text="\u{1F50D} Finding deployed function...";let r=(await new T(u.getApiConfig()).listFunctions()).find(a=>a.name===s);if(!r)throw new Error(`Function '${s}' not found in project. Make sure it's deployed first.`);c.text="\u{1F4E4} Uploading documentation content...",t.info("Documentation content ready for update"),c.succeed("\u2705 Documentation updated!"),t.newline(),t.success(`\u{1F4C4} Documentation updated for deployed function: ${Ve.default.cyan(s)}`),t.info(""),t.info("\u2728 Your function documentation has been updated:"),t.info(` \u2022 Function ID: ${Ve.default.gray(r.id)}`),t.info(` \u2022 Source: ${Ve.default.gray("Local README.md")}`),t.info(` \u2022 Updated: ${Ve.default.gray(new Date().toLocaleString())}`),t.info(` \u2022 View in dashboard: ${Ve.default.cyan("Dashboard \u2192 Functions \u2192 "+s)}`),t.newline(),t.info("\u{1F4A1} The updated documentation is now available in the dashboard!")}async function Er(){t.newline(),t.success(`\u{1F4C4} Documentation updated in: ${Ve.default.cyan("README.md")}`),t.info(""),t.info("\u2728 Your function documentation is ready:"),t.info(" \u2022 Review and edit the AI-generated content as needed"),t.info(" \u2022 Sinch-themed diagrams will render in markdown viewers"),t.info(" \u2022 File is ready for version control and deployment"),t.newline(),t.info("\u{1F4A1} Popular markdown viewers:"),t.info(" \u2022 VS Code (built-in)"),t.info(" \u2022 GitHub (drag & drop file)"),t.info(" \u2022 Typora, Mark Text, or any markdown app")}Yi.exports=bn});var ns=R((Nc,ts)=>{"use strict";var V=h(require("chalk")),Sn=h(require("inquirer")),Qi=require("commander"),de=h(require("fs-extra")),xe=h(require("path")),Xi=h(require("adm-zip"));z();k();A();E();var es=new Qi.Command("download");es.description("Download function source code").argument("[function-id]","Function ID to download (ULID format)").option("-o, --output <dir>","Output directory (default: ./functions/<function-name>)").option("--no-extract","Keep as ZIP file without extracting").option("--non-interactive","Skip interactive selection").option("-f, --force","Overwrite existing directory without prompting").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig()),i=s;if(!i&&!e.nonInteractive){let d=await xr(n);if(!d){t.info("Download cancelled");return}i=d}i||(t.error("Function ID required. Provide as argument or select interactively"),t.info(`Usage: ${V.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABCDE")}`),t.info(` or: ${V.default.cyan("sinch functions download")} (interactive selection)`),process.exit(1)),c.start("\u{1F4E1} Fetching function metadata...");let o=await n.getFunction(i);c.succeed("Function metadata loaded");let r=xe.join("functions",o.name),a=e.output||r,l=xe.resolve(a);if(await de.pathExists(l)){if(!e.force){let{overwrite:d}=await Sn.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${a}' already exists. Overwrite?`,default:!1}]);if(!d){t.info("Download cancelled");return}}c.start("\u{1F5D1}\uFE0F Removing existing directory..."),await de.remove(l),c.succeed("Existing directory removed")}c.start("\u{1F4E5} Downloading function source code...");let p=await n.downloadFunction(i);if(c.succeed("Source code downloaded"),e.extract!==!1){c.start("\u{1F4E6} Extracting files..."),await de.ensureDir(l);let d=new Xi.default(p),f=d.getEntries();d.extractAllTo(l,!0),c.succeed(`\u{1F4E6} Extracted ${f.length} files`);let g=xe.join(l,"sinch-metadata.json"),w={functionId:o.id,name:o.name,runtime:o.runtime,status:o.status,downloadedAt:new Date().toISOString(),url:o.containerAppUrl,configuration:o.configuration};await de.writeJson(g,w,{spaces:2}),t.newline(),t.success("\u2705 Function downloaded successfully!"),t.newline(),t.info(`\u{1F4C1} Location: ${V.default.cyan(a)}`),t.info(`\u{1F4CB} Files: ${f.length} files extracted`);let y=xe.join(l,"sinch.json");await de.pathExists(y)&&t.info("\u{1F527} Config: sinch.json found"),t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 Navigate: ${V.default.cyan(`cd ${a}`)}`),t.info(` \u2022 Run locally: ${V.default.cyan("sinch functions dev")}`),t.info(` \u2022 Deploy changes: ${V.default.cyan("sinch functions deploy")}`)}else{let d=`${o.name}.zip`,f=e.output?xe.resolve(e.output):xe.resolve(d);c.start(`\u{1F4BE} Saving as ${d}...`),await de.writeFile(f,p),c.succeed("ZIP file saved"),t.newline(),t.success("\u2705 Function downloaded as ZIP!"),t.info(`\u{1F4C1} File: ${V.default.cyan(f)}`),t.info(`\u{1F4E6} Size: ${(p.length/1024).toFixed(2)} KB`)}}catch(n){c.stop(),n.message.includes("404")||n.message.includes("not found")?(t.error(`Function not found with ID: ${s}`),t.info("\u{1F4A1} List available functions with:"),t.info(` ${V.default.cyan("sinch functions list")}`),t.info("\u{1F4A1} Or use interactive selection:"),t.info(` ${V.default.cyan("sinch functions download")}`)):t.error(`Failed to download function: ${n.message}`),process.exit(1)}});async function xr(s){try{c.start("\u{1F4CB} Loading functions...");let e=await s.listFunctions();if(c.stop(),!e.functions||e.functions.length===0)return t.warn("No functions found to download"),null;let n=e.functions.map(o=>({name:`${V.default.cyan(o.name.padEnd(20))} ${V.default.yellow(o.runtime.padEnd(8))} ${Dr(o.status)}`,value:o.id,short:o.name}));t.newline();let{selectedFunction:i}=await Sn.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function to download:",choices:n,pageSize:15}]);return i}catch(e){throw c.stop(),e}}function Dr(s){return{Running:V.default.green("\u2705 Running"),Failed:V.default.red("\u274C Failed"),Pending:V.default.yellow("\u23F3 Pending"),Building:V.default.blue("\u{1F528} Building")}[s]||V.default.gray(s)}ts.exports=es});var os=R((Oc,ss)=>{"use strict";var is=require("commander"),jr=oi(),Rr=di(),Nr=Ii(),Or=xi(),Tr=Oi(),Fr=Bi(),Lr=Wi(),_r=Zi(),Ur=ns(),pe=new is.Command("functions");pe.description("Manage Sinch Functions");pe.addCommand(jr);pe.addCommand(Rr);pe.addCommand(Nr);pe.addCommand(Ur);pe.addCommand(Or);pe.addCommand(Tr);pe.addCommand(Fr);pe.addCommand(Lr);pe.addCommand(_r);ss.exports=pe});var cs=R((Uc,as)=>{"use strict";var rs=require("commander"),ie=h(require("chalk"));z();k();A();E();var me=new rs.Command("templates");me.description("Browse and manage function templates");me.command("list").alias("ls").description("List available templates").argument("[runtime]","Filter by runtime (node, csharp, python)").option("-c, --category <category>","Filter by category (voice, sms, verification)").option("-d, --detailed","Show detailed information").action(async(s,e)=>{try{await u.load();let n=new T(u.getApiConfig());c.start("Loading templates...");let i;if(s?i=await n.listRuntimeTemplates(s,e.category):i=await n.listAllTemplates(e.category),c.stop(),i.templates.length===0){t.info(`No templates found${s?` for ${s}`:""}${e.category?` in category ${e.category}`:""}`);return}let o=`Available Templates${s?` (${s})`:""}${e.category?` - ${e.category}`:""}`;if(t.title(o),e.detailed)i.templates.forEach((r,a)=>{a>0&&t.newline(),t.log(ie.default.bold.blue(`${r.name}`)),t.log(` Runtime: ${r.runtime}`),t.log(` Category: ${r.category}`),t.log(` Description: ${r.description}`),r.tags&&r.tags.length>0&&t.log(` Tags: ${r.tags.map(l=>ie.default.gray(l)).join(", ")}`),t.log(` Path: ${ie.default.gray(r.path)}`)});else{let r=i.templates.map(a=>[a.name,a.runtime,a.category,a.description.substring(0,50)+(a.description.length>50?"...":""),a.tags?a.tags.slice(0,2).join(", ")+(a.tags.length>2?"...":""):""]);t.table(["Name","Runtime","Category","Description","Tags"],r)}t.newline(),t.info(`Found ${i.templates.length} template${i.templates.length===1?"":"s"}`),t.info('Use "sinch templates show <runtime>/<template>" for details')}catch(n){c.stop(),t.error(`Failed to list templates: ${n.message}`),process.exit(1)}});me.command("show").description("Show detailed template information").argument("<template>",'Template name in format "runtime/template-name"').action(async s=>{try{await u.load();let e=new T(u.getApiConfig());if(!s.includes("/"))throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');let n=s.split("/"),i=n[0],o=n[1];if(!i||!o)throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');c.start(`Loading template details for ${s}...`);let r=await e.getTemplateDetails(i,o);c.stop(),t.title(`Template: ${r.name}`),t.newline(),t.log(ie.default.bold("Basic Information:")),t.log(` Runtime: ${r.runtime}`),t.log(` Category: ${r.category}`),t.log(` Description: ${r.description}`),r.tags&&r.tags.length>0&&t.log(` Tags: ${r.tags.map(a=>ie.default.blue(a)).join(", ")}`),r.variables&&Object.keys(r.variables).length>0&&(t.newline(),t.log(ie.default.bold("Template Variables:")),Object.entries(r.variables).forEach(([a,l])=>{t.log(` ${a}: ${ie.default.gray(l)}`)})),r.files&&r.files.length>0&&(t.newline(),t.log(ie.default.bold("Files:")),r.files.forEach(a=>{t.log(` ${ie.default.gray("\u2022")} ${a}`)})),r.readmeContent&&(t.newline(),t.log(ie.default.bold("README:")),r.readmeContent.split(`
89
89
  `).slice(0,10).forEach(l=>{t.log(` ${ie.default.gray(l)}`)}),r.readmeContent.split(`
90
- `).length>10&&t.log(` ${ie.default.gray("... (truncated)")}`)),t.newline(),t.info(`Use "sinch functions init --template ${s}" to create a function from this template`)}catch(e){c.stop(),t.error(`Failed to show template details: ${e.message}`),process.exit(1)}});me.command("node").description("List Node.js templates").option("-c, --category <category>","Filter by category").action(async s=>{let e=me.commands.find(n=>n.name()==="list");e&&await e.action("node",s)});me.command("csharp").description("List C# templates").option("-c, --category <category>","Filter by category").action(async s=>{let e=me.commands.find(n=>n.name()==="list");e&&await e.action("csharp",s)});me.command("python").description("List Python templates").option("-c, --category <category>","Filter by category").action(async s=>{let e=me.commands.find(n=>n.name()==="list");e&&await e.action("python",s)});as.exports=me});var us=R((Jc,ps)=>{"use strict";var ls=require("commander"),He=h(require("chalk")),ds=h(require("inquirer"));k();A();E();var $t=new ls.Command("voice");$t.description("Manage Sinch Voice applications and settings");$t.command("callback-url").alias("webhook").description("Update webhook callback URL for your Voice application").argument("[url]","New callback URL (if not provided, will prompt)").option("-a, --app-key <key>","Application key (if not provided, will show selection)").action(async(s,e)=>{try{await u.load(),await vn()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await Ur(),i=e.appKey;if(!i){let o=u.getPublicCredentialInfo()?.applicationKey;o||(t.error('No default application key found. Run "sinch auth login" first.'),process.exit(1)),i=o,t.info(`Using default application: ${i}`)}if(!s){let{newUrl:o}=await ds.default.prompt([{type:"input",name:"newUrl",message:"Enter new callback URL:",validate:r=>{if(!r)return"URL is required";try{return new URL(r),!0}catch{return"Please enter a valid URL"}}}]);s=o}c.start("Updating callback URL...");try{let o=await n.voice.applications.get(i),r={...o,capability:{...o.capability,voice:{...o.capability?.voice,webhooks:{...o.capability?.voice?.webhooks,url:s,method:"POST"}}}};await n.voice.applications.update(i,r),c.succeed("Callback URL updated successfully!"),t.newline(),t.info(`Application: ${o.displayName||i}`),t.info(`New callback URL: ${s}`),t.newline(),t.info("\u{1F389} Your Voice functions will now receive webhooks at this URL"),t.info("\u{1F4A1} Test with: sinch functions dev --tunnel")}catch(o){throw c.fail("Failed to update callback URL"),o}}catch(n){c.stop(),t.error(`Failed to update callback URL: ${n.message}`),process.exit(1)}});$t.command("get-callbacks").description("Get current callback URLs with full debug output").option("-a, --app-key <key>","Application key (defaults to stored app key)").option("--curl","Show equivalent curl command").action(async s=>{try{await u.load(),await vn()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=await u.getApplicationCredentials();e||(t.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let n=s.appKey||e.applicationKey;if(t.info("\u{1F50D} Getting callback URLs..."),t.newline(),s.curl){let i=`${e.applicationKey}:${e.applicationSecret}`,o=Buffer.from(i).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(He.default.gray("```bash"));let r=`curl -X GET \\
90
+ `).length>10&&t.log(` ${ie.default.gray("... (truncated)")}`)),t.newline(),t.info(`Use "sinch functions init --template ${s}" to create a function from this template`)}catch(e){c.stop(),t.error(`Failed to show template details: ${e.message}`),process.exit(1)}});me.command("node").description("List Node.js templates").option("-c, --category <category>","Filter by category").action(async s=>{let e=me.commands.find(n=>n.name()==="list");e&&await e.action("node",s)});me.command("csharp").description("List C# templates").option("-c, --category <category>","Filter by category").action(async s=>{let e=me.commands.find(n=>n.name()==="list");e&&await e.action("csharp",s)});me.command("python").description("List Python templates").option("-c, --category <category>","Filter by category").action(async s=>{let e=me.commands.find(n=>n.name()==="list");e&&await e.action("python",s)});as.exports=me});var us=R((Bc,ps)=>{"use strict";var ls=require("commander"),He=h(require("chalk")),ds=h(require("inquirer"));k();A();E();var $t=new ls.Command("voice");$t.description("Manage Sinch Voice applications and settings");$t.command("callback-url").alias("webhook").description("Update webhook callback URL for your Voice application").argument("[url]","New callback URL (if not provided, will prompt)").option("-a, --app-key <key>","Application key (if not provided, will show selection)").action(async(s,e)=>{try{await u.load(),await vn()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await qr(),i=e.appKey;if(!i){let o=u.getPublicCredentialInfo()?.applicationKey;o||(t.error('No default application key found. Run "sinch auth login" first.'),process.exit(1)),i=o,t.info(`Using default application: ${i}`)}if(!s){let{newUrl:o}=await ds.default.prompt([{type:"input",name:"newUrl",message:"Enter new callback URL:",validate:r=>{if(!r)return"URL is required";try{return new URL(r),!0}catch{return"Please enter a valid URL"}}}]);s=o}c.start("Updating callback URL...");try{let o=await n.voice.applications.get(i),r={...o,capability:{...o.capability,voice:{...o.capability?.voice,webhooks:{...o.capability?.voice?.webhooks,url:s,method:"POST"}}}};await n.voice.applications.update(i,r),c.succeed("Callback URL updated successfully!"),t.newline(),t.info(`Application: ${o.displayName||i}`),t.info(`New callback URL: ${s}`),t.newline(),t.info("\u{1F389} Your Voice functions will now receive webhooks at this URL"),t.info("\u{1F4A1} Test with: sinch functions dev --tunnel")}catch(o){throw c.fail("Failed to update callback URL"),o}}catch(n){c.stop(),t.error(`Failed to update callback URL: ${n.message}`),process.exit(1)}});$t.command("get-callbacks").description("Get current callback URLs with full debug output").option("-a, --app-key <key>","Application key (defaults to stored app key)").option("--curl","Show equivalent curl command").action(async s=>{try{await u.load(),await vn()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=await u.getApplicationCredentials();e||(t.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let n=s.appKey||e.applicationKey;if(t.info("\u{1F50D} Getting callback URLs..."),t.newline(),s.curl){let i=`${e.applicationKey}:${e.applicationSecret}`,o=Buffer.from(i).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(He.default.gray("```bash"));let r=`curl -X GET \\
91
91
  https://calling.api.sinch.com/calling/v1/applications/${n}/callbacks/urls \\
92
92
  -H "Authorization: Basic ${o}"`;t.info(He.default.cyan(r)),t.info(He.default.gray("```")),t.newline()}try{let{SinchClient:i}=require("@sinch/sdk-core"),o=new i({applicationKey:e.applicationKey,applicationSecret:e.applicationSecret});c.start("Fetching callback URLs...");let r=await o.voice.applications.getCallbackURLs({applicationkey:n});c.succeed("Callback URLs retrieved"),t.newline(),t.info("\u{1F4E5} Current Callback Configuration:"),t.info(` currentCallbacks.primary: ${r?.primary||"undefined"}`),t.info(` currentCallbacks.fallback: ${r?.fallback||"undefined"}`)}catch(i){c.fail("Failed to get callback URLs"),t.error(`Error: ${i.message}`),t.newline(),t.info("Full error details:"),t.info(JSON.stringify(i,null,2))}}catch(e){t.error(`Command failed: ${e.message}`),process.exit(1)}});$t.command("set-callback").description("Update callback URL with debug output showing exact API call").argument("<url>","Callback URL to set").option("-a, --app-key <key>","Application key (defaults to stored app key)").option("--primary-only","Only set primary URL (no fallback)").option("--debug","Show full curl command and response").action(async(s,e)=>{try{await u.load(),await vn()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await u.getApplicationCredentials();n||(t.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let i=e.appKey||n.applicationKey;t.info("\u{1F527} Updating callback URL with debug output..."),t.newline();let o=e.primaryOnly?{url:{primary:s}}:{url:{primary:s,fallback:s}},r=`${n.applicationKey}:${n.applicationSecret}`,a=Buffer.from(r).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(He.default.gray("```bash"));let l=`curl -X POST \\
93
93
  https://calling.api.sinch.com/calling/v1/applications/${i}/callbacks/urls \\
94
94
  -H "Authorization: Basic ${a}" \\
95
95
  -H "Content-Type: application/json" \\
96
- -d '${JSON.stringify(o,null,2)}'`;t.info(He.default.cyan(l)),t.info(He.default.gray("```")),t.newline();try{let{SinchClient:p}=require("@sinch/sdk-core"),d=new p({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret});t.info("\u{1F4E4} Request Body:"),t.info(JSON.stringify(o,null,2)),t.newline(),c.start("Sending update request..."),await d.voice.applications.updateCallbackURLs({applicationkey:i,updateCallbacksRequestBody:o}),c.succeed("Update request sent"),c.start("Waiting for changes to propagate..."),await new Promise(w=>setTimeout(w,5e3)),c.start("Verifying update...");let f=await d.voice.applications.getCallbackURLs({applicationkey:i});c.succeed("Verification complete"),t.newline(),t.info("\u{1F4E5} Current Callback URLs:"),t.info(JSON.stringify(f,null,2));let g=f?.url||f?.primary||f?.urls?.primary;g===s?(t.newline(),t.success("\u2705 Callback URL successfully updated!")):(t.newline(),t.warn("\u26A0\uFE0F Callback URL may not have been updated correctly"),t.info("Expected: "+s),t.info("Actual: "+(typeof g=="object"?JSON.stringify(g):g||"not found")),t.newline(),t.info("\u{1F50D} Debug - Response structure:"),t.info(" typeof currentCallbacks: "+typeof f),t.info(" currentCallbacks.url: "+(f?.url||"undefined")),t.info(" currentCallbacks.primary: "+(f?.primary||"undefined")),t.info(" currentCallbacks.urls?.primary: "+(f?.urls?.primary||"undefined")))}catch(p){c.fail("Update failed"),t.error(`Error: ${p.message}`),e.debug&&(t.newline(),t.info("Full error details:"),t.info(JSON.stringify(p,null,2)))}}catch(n){t.error(`Command failed: ${n.message}`),process.exit(1)}});async function vn(){return await u.hasCredentials()}async function Ur(){return await u.createSinchClient()}ps.exports=$t});var ms=R((Kc,gs)=>{"use strict";var fs=require("commander"),Ce=h(require("keytar")),q=h(require("chalk"));A();var $n=h(require("inquirer")),De="sinch-functions-cli",ze=new fs.Command("secrets");ze.description("Manage secure secrets in OS keychain").addHelpText("after",`
96
+ -d '${JSON.stringify(o,null,2)}'`;t.info(He.default.cyan(l)),t.info(He.default.gray("```")),t.newline();try{let{SinchClient:p}=require("@sinch/sdk-core"),d=new p({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret});t.info("\u{1F4E4} Request Body:"),t.info(JSON.stringify(o,null,2)),t.newline(),c.start("Sending update request..."),await d.voice.applications.updateCallbackURLs({applicationkey:i,updateCallbacksRequestBody:o}),c.succeed("Update request sent"),c.start("Waiting for changes to propagate..."),await new Promise(w=>setTimeout(w,5e3)),c.start("Verifying update...");let f=await d.voice.applications.getCallbackURLs({applicationkey:i});c.succeed("Verification complete"),t.newline(),t.info("\u{1F4E5} Current Callback URLs:"),t.info(JSON.stringify(f,null,2));let g=f?.url||f?.primary||f?.urls?.primary;g===s?(t.newline(),t.success("\u2705 Callback URL successfully updated!")):(t.newline(),t.warn("\u26A0\uFE0F Callback URL may not have been updated correctly"),t.info("Expected: "+s),t.info("Actual: "+(typeof g=="object"?JSON.stringify(g):g||"not found")),t.newline(),t.info("\u{1F50D} Debug - Response structure:"),t.info(" typeof currentCallbacks: "+typeof f),t.info(" currentCallbacks.url: "+(f?.url||"undefined")),t.info(" currentCallbacks.primary: "+(f?.primary||"undefined")),t.info(" currentCallbacks.urls?.primary: "+(f?.urls?.primary||"undefined")))}catch(p){c.fail("Update failed"),t.error(`Error: ${p.message}`),e.debug&&(t.newline(),t.info("Full error details:"),t.info(JSON.stringify(p,null,2)))}}catch(n){t.error(`Command failed: ${n.message}`),process.exit(1)}});async function vn(){return await u.hasCredentials()}async function qr(){return await u.createSinchClient()}ps.exports=$t});var ms=R((Vc,gs)=>{"use strict";var fs=require("commander"),Ce=h(require("keytar")),q=h(require("chalk"));A();var $n=h(require("inquirer")),De="sinch-functions-cli",ze=new fs.Command("secrets");ze.description("Manage secure secrets in OS keychain").addHelpText("after",`
97
97
  Examples:
98
98
  ${q.default.cyan("sinch secrets list")} List all custom secrets
99
99
  ${q.default.cyan("sinch secrets add API_KEY abc123")} Add or update a secret
@@ -104,7 +104,7 @@ Note: Secrets are stored securely in your OS keychain:
104
104
  - Windows: Credential Manager
105
105
  - macOS: Keychain
106
106
  - Linux: Secret Service API
107
- `);ze.command("list").description("List all custom secrets (keys only)").action(async()=>{try{let e=(await Ce.default.findCredentials(De)).filter(n=>n.account&&n.account.startsWith("custom-")).map(n=>n.account.replace("custom-",""));if(e.length===0){t.info("No custom secrets found"),t.info(""),t.info("\u{1F4A1} Add a secret with:"),t.info(` ${q.default.cyan("sinch secrets add <KEY> <VALUE>")}`);return}t.info(q.default.bold("Custom Secrets:")),t.info(""),e.forEach(n=>{t.info(` \u{1F510} ${q.default.cyan(n)}`)}),t.info(""),t.info(`Total: ${e.length} secret(s)`)}catch(s){t.error("Failed to list secrets:",s.message),process.exit(1)}});ze.command("add <key> <value>").description("Add or update a secret in OS keychain").action(async(s,e)=>{try{s.match(/^[A-Z0-9_]+$/)||(t.error("Secret key must be uppercase letters, numbers, and underscores only"),t.info(`Example: ${q.default.cyan("API_KEY")}, ${q.default.cyan("DATABASE_PASSWORD")}`),process.exit(1));let n=`custom-${s}`,o=await Ce.default.getPassword(De,n)!==null;await Ce.default.setPassword(De,n,e),o?t.success(`\u2705 Updated secret: ${q.default.cyan(s)}`):t.success(`\u2705 Added secret: ${q.default.cyan(s)}`),t.info(""),t.info("\u{1F4DD} To use in your function:"),t.info(` 1. Add ${q.default.cyan(s+"=")} to your .env file (leave value empty)`),t.info(` 2. Access via ${q.default.cyan("process.env."+s)} in your code`),t.info(" 3. The secret will be loaded automatically from OS keychain")}catch(n){t.error("Failed to add secret:",n.message),process.exit(1)}});ze.command("get <key>").description("Get a specific secret value").option("--show","Show the actual value (be careful!)").action(async(s,e)=>{try{let n=`custom-${s}`,i=await Ce.default.getPassword(De,n);i||(t.error(`Secret not found: ${q.default.cyan(s)}`),t.info(""),t.info("\u{1F4A1} Available secrets:"),t.info(` Run ${q.default.cyan("sinch secrets list")} to see all secrets`),process.exit(1)),t.info(`Secret: ${q.default.cyan(s)}`),e.show?(t.warn("\u26A0\uFE0F Showing secret value - be careful not to expose it!"),t.info(`Value: ${i}`)):(t.info(`Value: ${q.default.gray("[HIDDEN - use --show to reveal]")}`),t.info(`Length: ${i.length} characters`))}catch(n){t.error("Failed to get secret:",n.message),process.exit(1)}});ze.command("delete <key>").alias("remove").alias("rm").description("Remove a secret from OS keychain").option("-f, --force","Skip confirmation").action(async(s,e)=>{try{let n=`custom-${s}`;if(await Ce.default.getPassword(De,n)||(t.error(`Secret not found: ${q.default.cyan(s)}`),process.exit(1)),!e.force&&!(await $n.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete secret '${s}'?`,default:!1}])).confirm){t.info("Cancelled");return}await Ce.default.deletePassword(De,n)?t.success(`\u2705 Deleted secret: ${q.default.cyan(s)}`):(t.error("Failed to delete secret"),process.exit(1))}catch(n){t.error("Failed to delete secret:",n.message),process.exit(1)}});ze.command("clear").description("Remove ALL custom secrets (use with caution!)").option("-f, --force","Skip confirmation").action(async s=>{try{let n=(await Ce.default.findCredentials(De)).filter(o=>o.account&&o.account.startsWith("custom-"));if(n.length===0){t.info("No custom secrets to clear");return}if(!s.force&&(t.warn(`\u26A0\uFE0F This will delete ${n.length} custom secret(s)`),!(await $n.default.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to delete ALL custom secrets?",default:!1}])).confirm)){t.info("Cancelled");return}let i=0;for(let o of n)await Ce.default.deletePassword(De,o.account)&&i++;t.success(`\u2705 Deleted ${i} custom secret(s)`)}catch(e){t.error("Failed to clear secrets:",e.message),process.exit(1)}});gs.exports=ze});var Ss=R((Hc,bs)=>{"use strict";var hs=require("commander"),L=h(require("chalk")),F=h(require("fs-extra")),W=h(require("path")),ys=h(require("os"));A();function ws(){return W.default.join(__dirname,"..","skills")}function In(){return W.default.join(ys.default.homedir(),".claude","skills","sinch-functions")}function kn(){return W.default.join(process.cwd(),".claude","skills","sinch-functions")}function Pn(){return W.default.join(process.cwd(),".github","skills","sinch-functions")}function Cs(s={}){let e=[],n=In();if(e.push({tool:"Claude Code",path:n,type:"global",installed:F.default.existsSync(W.default.join(n,"SKILL.md"))}),s.project){let i=kn();e.push({tool:"Claude Code",path:i,type:"project",installed:F.default.existsSync(W.default.join(i,"SKILL.md"))})}if(s.project){let i=Pn();e.push({tool:"GitHub Copilot",path:i,type:"project",installed:F.default.existsSync(W.default.join(i,"SKILL.md"))})}return e}var st=new hs.Command("skills");st.description("Manage AI coding assistant skills for Sinch development").addHelpText("after",`
107
+ `);ze.command("list").description("List all custom secrets (keys only)").action(async()=>{try{let e=(await Ce.default.findCredentials(De)).filter(n=>n.account&&n.account.startsWith("custom-")).map(n=>n.account.replace("custom-",""));if(e.length===0){t.info("No custom secrets found"),t.info(""),t.info("\u{1F4A1} Add a secret with:"),t.info(` ${q.default.cyan("sinch secrets add <KEY> <VALUE>")}`);return}t.info(q.default.bold("Custom Secrets:")),t.info(""),e.forEach(n=>{t.info(` \u{1F510} ${q.default.cyan(n)}`)}),t.info(""),t.info(`Total: ${e.length} secret(s)`)}catch(s){t.error("Failed to list secrets:",s.message),process.exit(1)}});ze.command("add <key> <value>").description("Add or update a secret in OS keychain").action(async(s,e)=>{try{s.match(/^[A-Z0-9_]+$/)||(t.error("Secret key must be uppercase letters, numbers, and underscores only"),t.info(`Example: ${q.default.cyan("API_KEY")}, ${q.default.cyan("DATABASE_PASSWORD")}`),process.exit(1));let n=`custom-${s}`,o=await Ce.default.getPassword(De,n)!==null;await Ce.default.setPassword(De,n,e),o?t.success(`\u2705 Updated secret: ${q.default.cyan(s)}`):t.success(`\u2705 Added secret: ${q.default.cyan(s)}`),t.info(""),t.info("\u{1F4DD} To use in your function:"),t.info(` 1. Add ${q.default.cyan(s+"=")} to your .env file (leave value empty)`),t.info(` 2. Access via ${q.default.cyan("process.env."+s)} in your code`),t.info(" 3. The secret will be loaded automatically from OS keychain")}catch(n){t.error("Failed to add secret:",n.message),process.exit(1)}});ze.command("get <key>").description("Get a specific secret value").option("--show","Show the actual value (be careful!)").action(async(s,e)=>{try{let n=`custom-${s}`,i=await Ce.default.getPassword(De,n);i||(t.error(`Secret not found: ${q.default.cyan(s)}`),t.info(""),t.info("\u{1F4A1} Available secrets:"),t.info(` Run ${q.default.cyan("sinch secrets list")} to see all secrets`),process.exit(1)),t.info(`Secret: ${q.default.cyan(s)}`),e.show?(t.warn("\u26A0\uFE0F Showing secret value - be careful not to expose it!"),t.info(`Value: ${i}`)):(t.info(`Value: ${q.default.gray("[HIDDEN - use --show to reveal]")}`),t.info(`Length: ${i.length} characters`))}catch(n){t.error("Failed to get secret:",n.message),process.exit(1)}});ze.command("delete <key>").alias("remove").alias("rm").description("Remove a secret from OS keychain").option("-f, --force","Skip confirmation").action(async(s,e)=>{try{let n=`custom-${s}`;if(await Ce.default.getPassword(De,n)||(t.error(`Secret not found: ${q.default.cyan(s)}`),process.exit(1)),!e.force&&!(await $n.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete secret '${s}'?`,default:!1}])).confirm){t.info("Cancelled");return}await Ce.default.deletePassword(De,n)?t.success(`\u2705 Deleted secret: ${q.default.cyan(s)}`):(t.error("Failed to delete secret"),process.exit(1))}catch(n){t.error("Failed to delete secret:",n.message),process.exit(1)}});ze.command("clear").description("Remove ALL custom secrets (use with caution!)").option("-f, --force","Skip confirmation").action(async s=>{try{let n=(await Ce.default.findCredentials(De)).filter(o=>o.account&&o.account.startsWith("custom-"));if(n.length===0){t.info("No custom secrets to clear");return}if(!s.force&&(t.warn(`\u26A0\uFE0F This will delete ${n.length} custom secret(s)`),!(await $n.default.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to delete ALL custom secrets?",default:!1}])).confirm)){t.info("Cancelled");return}let i=0;for(let o of n)await Ce.default.deletePassword(De,o.account)&&i++;t.success(`\u2705 Deleted ${i} custom secret(s)`)}catch(e){t.error("Failed to clear secrets:",e.message),process.exit(1)}});gs.exports=ze});var Ss=R((zc,bs)=>{"use strict";var hs=require("commander"),L=h(require("chalk")),F=h(require("fs-extra")),W=h(require("path")),ys=h(require("os"));A();function ws(){return W.default.join(__dirname,"..","skills")}function In(){return W.default.join(ys.default.homedir(),".claude","skills","sinch-functions")}function kn(){return W.default.join(process.cwd(),".claude","skills","sinch-functions")}function Pn(){return W.default.join(process.cwd(),".github","skills","sinch-functions")}function Cs(s={}){let e=[],n=In();if(e.push({tool:"Claude Code",path:n,type:"global",installed:F.default.existsSync(W.default.join(n,"SKILL.md"))}),s.project){let i=kn();e.push({tool:"Claude Code",path:i,type:"project",installed:F.default.existsSync(W.default.join(i,"SKILL.md"))})}if(s.project){let i=Pn();e.push({tool:"GitHub Copilot",path:i,type:"project",installed:F.default.existsSync(W.default.join(i,"SKILL.md"))})}return e}var st=new hs.Command("skills");st.description("Manage AI coding assistant skills for Sinch development").addHelpText("after",`
108
108
  Examples:
109
109
  ${L.default.cyan("sinch skills install")} Install skills globally (Claude Code)
110
110
  ${L.default.cyan("sinch skills install --project")} Install to current project (Claude + Copilot)
@@ -116,8 +116,8 @@ Examples:
116
116
  Skills provide AI coding assistants with accurate Sinch development patterns.
117
117
  `);st.command("install").description("Install Sinch skills for AI coding assistants").option("--claude","Install for Claude Code only").option("--copilot","Install for GitHub Copilot only (requires --project)").option("--project","Install to current project (for team sharing via git)").option("--link","Symlink instead of copy (for development)").option("--force","Overwrite existing skills without prompting").action(async s=>{try{let e=ws();F.default.existsSync(e)||(t.error("Skills source not found. This may indicate a corrupted CLI installation."),t.info(`Expected path: ${e}`),process.exit(1));let n=W.default.join(e,"sinch-functions");F.default.existsSync(n)||(t.error("Skill source not found."),process.exit(1));let i=0,o=0,r=s.claude||!s.claude&&!s.copilot,a=s.copilot||!s.claude&&!s.copilot&&s.project;if(r){if(!s.project||s.claude){let l=In();F.default.existsSync(W.default.join(l,"SKILL.md"))&&!s.force?(t.warn(`Claude Code skill already installed at ${l}`),t.info("Use --force to overwrite"),o++):(await F.default.ensureDir(W.default.dirname(l)),s.link&&process.platform!=="win32"?(F.default.existsSync(l)&&await F.default.remove(l),await F.default.symlink(n,l,"junction"),t.success(`Linked Claude Code skill to ${l}`)):(await F.default.copy(n,l,{overwrite:!0}),t.success(`Installed Claude Code skill to ${l}`)),i++)}if(s.project){let l=kn();F.default.existsSync(W.default.join(l,"SKILL.md"))&&!s.force?(t.warn(`Claude Code project skill already installed at ${l}`),t.info("Use --force to overwrite"),o++):(await F.default.ensureDir(W.default.dirname(l)),await F.default.copy(n,l,{overwrite:!0}),t.success(`Installed Claude Code skill to ${l}`),i++)}}if(a&&s.project){let l=Pn();F.default.existsSync(W.default.join(l,"SKILL.md"))&&!s.force?(t.warn(`Copilot skill already installed at ${l}`),t.info("Use --force to overwrite"),o++):(await F.default.ensureDir(W.default.dirname(l)),await F.default.copy(n,l,{overwrite:!0}),t.success(`Installed Copilot skill to ${l}`),i++)}else s.copilot&&!s.project&&(t.warn("Copilot requires --project flag (no global installation supported)"),t.info("Use: sinch skills install --copilot --project"));t.info(""),i>0&&t.success(`Installed ${i} skill(s)`),o>0&&t.info(`Skipped ${o} existing skill(s)`),i>0&&(t.info(""),t.info(L.default.bold("Next steps:")),r&&(t.info(` ${L.default.cyan("\u2022")} Claude Code will now have Sinch expertise`),t.info(` ${L.default.cyan("\u2022")} Ask about voice IVRs, SVAML, or CLI commands`)),a&&s.project&&(t.info(` ${L.default.cyan("\u2022")} Copilot will use Sinch patterns for code suggestions`),t.info(` ${L.default.cyan("\u2022")} Commit .github/skills/ to share with team`)))}catch(e){t.error("Failed to install skills:",e.message),process.exit(1)}});st.command("list").description("Show installed skill locations").action(async()=>{try{let s=Cs({project:!0}),e=s.filter(a=>a.type==="global"),n=s.filter(a=>a.type==="project");t.info(L.default.bold(`Sinch Skills Installation Status
118
118
  `)),t.info(L.default.underline("Global (personal machine):"));let i=!1;for(let a of e)a.installed?(t.info(` ${L.default.green("\u2713")} ${a.tool}: ${L.default.gray(a.path)}`),i=!0):t.info(` ${L.default.gray("\u25CB")} ${a.tool}: ${L.default.gray("not installed")}`);i||t.info(` ${L.default.gray("No global skills installed")}`),t.info(""),t.info(L.default.underline("Project (current directory):"));let o=!1;for(let a of n)a.installed?(t.info(` ${L.default.green("\u2713")} ${a.tool}: ${L.default.gray(a.path)}`),o=!0):t.info(` ${L.default.gray("\u25CB")} ${a.tool}: ${L.default.gray("not installed")}`);o||t.info(` ${L.default.gray("No project skills installed")}`),t.info(""),s.some(a=>a.installed)||(t.info("Run `sinch skills install` to install skills globally"),t.info("Run `sinch skills install --project` to install for this project"))}catch(s){t.error("Failed to list skills:",s.message),process.exit(1)}});st.command("uninstall").description("Remove installed Sinch skills").option("--claude","Uninstall from Claude Code only").option("--copilot","Uninstall from GitHub Copilot only").option("--project","Uninstall from current project only").option("--all","Uninstall from all locations").action(async s=>{try{let e=0,n=!s.claude&&!s.copilot&&!s.project&&!s.all,i=s.all||n,o=s.project&&!s.all&&!n,r=s.claude||i||o,a=s.copilot||i||o;if(r){if(!o){let l=In();F.default.existsSync(l)&&(await F.default.remove(l),t.success(`Removed Claude Code skill from ${l}`),e++)}if(o||i){let l=kn();F.default.existsSync(l)&&(await F.default.remove(l),t.success(`Removed Claude Code skill from ${l}`),e++)}}if(a&&(o||i)){let l=Pn();F.default.existsSync(l)&&(await F.default.remove(l),t.success(`Removed Copilot skill from ${l}`),e++)}t.info(""),e>0?t.success(`Removed ${e} skill(s)`):t.info("No skills found to remove")}catch(e){t.error("Failed to uninstall skills:",e.message),process.exit(1)}});st.command("update").description("Update skills to latest version").option("--project","Update project skills as well").action(async s=>{try{t.info(`Updating Sinch skills...
119
- `);let n=Cs({project:s.project}).filter(a=>a.installed);if(n.length===0){t.info("No skills installed. Run `sinch skills install` first.");return}let i=ws(),o=W.default.join(i,"sinch-functions"),r=0;for(let a of n)await F.default.copy(o,a.path,{overwrite:!0}),t.success(`Updated ${a.tool} (${a.type})`),r++;t.info(""),t.success(`Updated ${r} skill(s)`)}catch(e){t.error("Failed to update skills:",e.message),process.exit(1)}});bs.exports=st});async function qr(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1))}async function O(){return await qr(),await u.createSinchClient()}function ot(s){let e=s||u.get("conversation-app-id");return e||(t.error("No Conversation App ID configured."),t.info("Set default: sinch config set conversation-app-id <id>"),t.info("Or specify: --app <app-id>"),process.exit(1)),e}var We=Q(()=>{"use strict";k();A()});var Ps=R((Xc,ks)=>{"use strict";var vs=require("commander"),$s=h(require("inquirer"));A();E();We();var Is=new vs.Command("send");Is.description("Send a message via Conversation API").argument("[recipient]","Recipient phone number (e.g., +15551234567)").argument("[message]","Message text to send").option("-c, --channel <channel>","Channel (SMS, WHATSAPP, MESSENGER, etc.)","SMS").option("-a, --app <app-id>","Conversation App ID (uses default if configured)").option("-m, --media <url>","Media URL for media messages").option("--caption <text>","Caption for media messages").option("-t, --template <name>","Template name for template messages").option("-p, --params <json>","Template parameters as JSON string").option("--location","Send location message").option("--lat <latitude>","Latitude for location messages",parseFloat).option("--lng <longitude>","Longitude for location messages",parseFloat).option("-n, --name <name>","Location name").option("--json","Output result as JSON").action(async(s,e,n)=>{try{let i=await O();if(!s||!e&&!n?.media&&!n?.template&&!n?.location){let r=await $s.default.prompt([{type:"input",name:"recipient",message:"Enter recipient phone number:",when:!s,validate:a=>a?a.startsWith("+")?!0:"Phone number must start with +":"Recipient is required"},{type:"input",name:"message",message:"Enter message:",when:!e&&!n?.media&&!n?.template&&!n?.location,validate:a=>a?!0:"Message is required"},{type:"list",name:"channel",message:"Select channel:",choices:["SMS","WHATSAPP","MESSENGER","INSTAGRAM","VIBER","TELEGRAM","RCS","LINE"],default:n?.channel||"SMS",when:!n?.channel}]);s=s||r.recipient,e=e||r.message,r.channel&&(n={...n,channel:r.channel})}let o=ot(n?.app);c.start("Sending message...");try{let r;if(n?.location)(!n.lat||!n.lng)&&(c.fail("Location messages require --lat and --lng"),process.exit(1)),r=await i.conversation.messages.send({sendMessageRequestBody:{app_id:o,recipient:{identified_by:{channel_identities:[{channel:n.channel||"SMS",identity:s}]}},message:{location_message:{coordinates:{latitude:n.lat,longitude:n.lng},title:n.name}}}});else if(n?.template){let a=n.params?JSON.parse(n.params):{};r=await i.conversation.messages.send({sendMessageRequestBody:{app_id:o,recipient:{identified_by:{channel_identities:[{channel:n.channel||"WHATSAPP",identity:s}]}},message:{template_message:{template_reference:{template_id:n.template,version:a.version||"1"},parameters:a}}}})}else n?.media?r=await i.conversation.messages.send({sendMessageRequestBody:{app_id:o,recipient:{identified_by:{channel_identities:[{channel:n.channel||"WHATSAPP",identity:s}]}},message:{media_message:{url:n.media,caption:n.caption}}}}):r=await i.conversation.messages.send({sendMessageRequestBody:{app_id:o,recipient:{identified_by:{channel_identities:[{channel:n?.channel||"SMS",identity:s}]}},message:{text_message:{text:e}}}});c.succeed("Message sent successfully!"),n?.json?console.log(JSON.stringify(r,null,2)):(t.newline(),t.info(`Message ID: ${r.message_id}`),t.info(`Recipient: ${s}`),t.info(`Channel: ${n?.channel||"SMS"}`))}catch(r){c.fail("Failed to send message"),t.error(`Error: ${r.message}`),(r.message?.includes("WHATSAPP")||r.message?.includes("channel not configured"))&&(t.newline(),t.info("To use WhatsApp, configure WhatsApp credentials in your Conversation app:"),t.info(" 1. Visit https://dashboard.sinch.com/convapi/apps"),t.info(" 2. Add WhatsApp channel credentials"),t.info(" 3. Verify your WhatsApp Business Account"),t.newline(),t.info("Or use SMS (no additional setup required):"),t.info(` sinch conversation send ${s} "${e}"`)),process.exit(1)}}catch(i){c.stop(),t.error(`Failed to send message: ${i.message}`),process.exit(1)}});ks.exports=Is});var xs=R((il,Es)=>{"use strict";var As=require("commander");A();E();We();var It=new As.Command("messages");It.description("Manage conversation messages");It.command("get").description("Get a specific message by ID").argument("<message-id>","Message ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await O();c.start("Fetching message...");let i=await n.conversation.messages.get({message_id:s});c.succeed("Message retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`Message ID: ${i.id}`),t.info(`Direction: ${i.direction}`),t.info(`Channel: ${i.channel_identity?.channel||"N/A"}`),t.info(`Contact ID: ${i.contact_id||"N/A"}`),t.info(`Conversation ID: ${i.conversation_id||"N/A"}`),t.info(`Status: ${i.accept_time?"Accepted":"Pending"}`),i.text_message&&t.info(`Text: ${i.text_message.text}`),i.media_message&&t.info(`Media URL: ${i.media_message.url}`))}catch(n){c.stop(),t.error(`Failed to get message: ${n.message}`),process.exit(1)}});It.command("list").description("List messages").option("-c, --channel <channel>","Filter by channel").option("-l, --limit <number>","Limit number of results",parseInt,20).option("--json","Output result as JSON").action(async s=>{try{let e=await O();c.start("Fetching messages...");let n=await e.conversation.messages.list({page_size:s.limit||20,...s.channel&&{channel:s.channel}});c.succeed(`Retrieved ${n.messages?.length||0} messages`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.messages&&n.messages.length>0?n.messages.forEach(i=>{t.info(`[${i.id}] ${i.direction} via ${i.channel_identity?.channel||"N/A"}`),i.text_message&&t.info(` "${i.text_message.text}"`),t.newline()}):t.info("No messages found"))}catch(e){c.stop(),t.error(`Failed to list messages: ${e.message}`),process.exit(1)}});It.command("delete").description("Delete a message").argument("<message-id>","Message ID to delete").action(async s=>{try{let e=await O();c.start("Deleting message..."),await e.conversation.messages.delete({message_id:s}),c.succeed("Message deleted successfully")}catch(e){c.stop(),t.error(`Failed to delete message: ${e.message}`),process.exit(1)}});Es.exports=It});var Rs=R((al,js)=>{"use strict";var Ds=require("commander"),Y=h(require("inquirer"));A();E();We();var Ut=class{sinchClient;constructor(e){this.sinchClient=e}hasChannel(e,n){return e.channel_identities?.some(i=>{let o=i.channel;return o==="CHANNEL_UNSPECIFIED"&&i.identity.includes("@")&&(o="EMAIL"),n.includes(o)})}getChannelIdentities(e,n){return e.channel_identities.filter(i=>{let o=i.channel;return o==="CHANNEL_UNSPECIFIED"&&i.identity.includes("@")&&(o="EMAIL"),n.includes(o)})}buildContactMenu(e){let n=this.hasChannel(e,["SMS","WHATSAPP"]),i=this.hasChannel(e,["SMS","WHATSAPP"]),o=this.hasChannel(e,["EMAIL"]),r=[];return n&&r.push({name:"\u{1F4AC} Send Message",value:"send-message"}),r.push({name:"Edit Name",value:"edit-name"}),i&&r.push({name:"Edit Phone",value:"edit-phone"}),o&&r.push({name:"Edit Email",value:"edit-email"}),r.push({name:"Delete Contact",value:"delete"},{name:"See More Details",value:"details"},{name:"\u2190 Back",value:"back"}),r}async sendMessage(e){let n=e.channel_identities.map(r=>{let a=r.channel;return a==="CHANNEL_UNSPECIFIED"&&r.identity.includes("@")&&(a="EMAIL"),{name:`${a}: ${r.identity}`,value:{channel:a,identity:r.identity}}});n.push({name:"\u2190 Back",value:"back"});let{selectedChannel:i}=await Y.default.prompt([{type:"list",name:"selectedChannel",message:"Select channel to send to:",choices:n}]);if(i==="back")return!1;let{messageText:o}=await Y.default.prompt([{type:"input",name:"messageText",message:"Enter your message:",validate:r=>r?!0:"Message is required"}]);try{let r=ot();c.start("Sending message...");let a=await this.sinchClient.conversation.messages.send({sendMessageRequestBody:{app_id:r,recipient:{identified_by:{channel_identities:[{channel:i.channel,identity:i.identity,app_id:""}]}},message:{text_message:{text:o}}}});c.succeed("Message sent successfully!"),t.newline(),t.info(`Message ID: ${a.message_id}`),t.info(`Recipient: ${i.identity}`),t.info(`Channel: ${i.channel}`),t.newline()}catch(r){c.fail("Failed to send message"),t.error(`Error: ${r.message}`),t.newline()}return!1}showDetails(e){t.newline(),t.info("Contact Details:"),t.info(`ID: ${e.id}`),t.info(`Display Name: ${e.display_name||"N/A"}`),t.info(`Email: ${e.email||"N/A"}`),t.info(`External ID: ${e.external_id||"N/A"}`),t.info(`Language: ${e.language||"N/A"}`),t.info(`Metadata: ${e.metadata||"N/A"}`),e.channel_identities&&e.channel_identities.length>0&&(t.newline(),t.info("Channel Identities:"),e.channel_identities.forEach(n=>{let i=n.channel;i==="CHANNEL_UNSPECIFIED"&&n.identity.includes("@")&&(i="EMAIL"),t.info(` ${i}: ${n.identity}`)})),t.newline()}async editName(e,n){let{newDisplayName:i}=await Y.default.prompt([{type:"input",name:"newDisplayName",message:"Enter new display name:",default:e.display_name}]);c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:n,display_name:i}),c.succeed("Contact updated successfully!"),e.display_name=i,t.newline()}async editChannelIdentities(e,n,i){let r={phone:{channels:["SMS","WHATSAPP"],addPrompt:"+ Add new phone number",selectPrompt:"Select phone number to edit or add new:",typePrompt:"Select type:",valuePrompt:"Enter phone number:",editPrompt:"Enter new phone number:",typeChoices:["SMS","WHATSAPP"],successAdd:"Phone number added successfully!",successEdit:"Phone number updated successfully!",successDelete:"Phone number deleted successfully!",validator:d=>d?d.startsWith("+")?!0:"Phone number must start with +":"Phone number is required"},email:{channels:["EMAIL"],addPrompt:"+ Add new email address",selectPrompt:"Select email address to edit or add new:",typePrompt:null,valuePrompt:"Enter email address:",editPrompt:"Enter new email address:",typeChoices:null,successAdd:"Email address added successfully!",successEdit:"Email address updated successfully!",successDelete:"Email address deleted successfully!",validator:d=>d?d.includes("@")?!0:"Invalid email address":"Email is required"}}[i],l=this.getChannelIdentities(e,r.channels).map(d=>{let f=e.channel_identities.indexOf(d),g=d.channel;return g==="CHANNEL_UNSPECIFIED"&&d.identity.includes("@")&&(g="EMAIL"),{name:`${g}: ${d.identity}`,value:f}});l.push({name:r.addPrompt,value:"add"}),l.push({name:"\u2190 Back",value:"cancel"});let{identityAction:p}=await Y.default.prompt([{type:"list",name:"identityAction",message:r.selectPrompt,choices:l}]);if(p!=="cancel")if(p==="add"){let d=[];r.typePrompt&&r.typeChoices&&d.push({type:"list",name:"newIdentityType",message:r.typePrompt,choices:r.typeChoices}),d.push({type:"input",name:"newIdentityValue",message:r.valuePrompt,validate:r.validator});let f=await Y.default.prompt(d);e.channel_identities.push({channel:f.newIdentityType||r.channels[0],identity:f.newIdentityValue,app_id:""}),c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:n,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(r.successAdd),t.newline()}else{let d=e.channel_identities[p],{editOrDelete:f}=await Y.default.prompt([{type:"list",name:"editOrDelete",message:"What would you like to do?",choices:["Edit","Delete","\u2190 Back"]}]);if(f==="Edit"){let{newValue:g}=await Y.default.prompt([{type:"input",name:"newValue",message:r.editPrompt,default:d.identity,validate:r.validator}]);d.identity=g,c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:n,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(r.successEdit),t.newline()}else f==="Delete"&&(e.channel_identities.splice(p,1),c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:n,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(r.successDelete),t.newline())}}async deleteContact(e,n,i){let{confirmDelete:o}=await Y.default.prompt([{type:"confirm",name:"confirmDelete",message:`Are you sure you want to delete "${e.display_name||"this contact"}"?`,default:!1}]);if(o){c.start("Deleting contact..."),await this.sinchClient.conversation.contact.delete({contact_id:n}),c.succeed("Contact deleted successfully");let r=i.findIndex(a=>a.id===n);if(r>-1&&i.splice(r,1),i.length===0)return t.info("No more contacts."),!0;t.newline()}return!1}async handleAction(e,n,i,o){switch(e){case"send-message":return await this.sendMessage(n);case"details":return this.showDetails(n),!1;case"edit-name":return await this.editName(n,i),!1;case"edit-phone":return await this.editChannelIdentities(n,i,"phone"),!1;case"edit-email":return await this.editChannelIdentities(n,i,"email"),!1;case"delete":return await this.deleteContact(n,i,o);default:return!1}}async runInteractiveList(e){let n=!0;for(;n;){let i=[];e.forEach(p=>{i.push(new Y.default.Separator(`
120
- ${p.display_name||"No name"}`)),p.channel_identities&&p.channel_identities.length>0&&p.channel_identities.forEach(d=>{let f=d.channel;f==="CHANNEL_UNSPECIFIED"&&d.identity.includes("@")&&(f="EMAIL"),i.push(new Y.default.Separator(`${f}: ${d.identity}`))}),i.push({name:"Edit Delete More",value:`menu:${p.id}`})}),i.push(new Y.default.Separator("")),i.push({name:"\u2190 Exit",value:"exit"});let{action:o}=await Y.default.prompt([{type:"list",name:"action",message:"Contacts",choices:i,pageSize:20}]);if(o==="exit")break;if(!o||!o.includes(":"))continue;let[r,a]=o.split(":"),l=e.find(p=>p.id===a);if(r==="menu"){let p=this.buildContactMenu(l),{subAction:d}=await Y.default.prompt([{type:"list",name:"subAction",message:`Actions for ${l.display_name||"contact"}:`,choices:p}]);if(d==="back")continue;await this.handleAction(d,l,a,e)&&(n=!1)}}}},je=new Ds.Command("contacts");je.description("Manage conversation contacts");je.command("create").description("Create a new contact").option("-p, --phone <number>","Phone number").option("-e, --email <email>","Email address").option("-n, --name <name>","Contact name").option("-d, --display-name <name>","Display name").option("--json","Output result as JSON").action(async s=>{try{if(!s.phone&&!s.email){let r=await Y.default.prompt([{type:"input",name:"phone",message:"Enter phone number (optional):",validate:a=>a&&!a.startsWith("+")?"Phone number must start with +":!0},{type:"input",name:"email",message:"Enter email address (optional):"},{type:"input",name:"name",message:"Enter contact name (optional):"}]);s={...s,...r}}!s.phone&&!s.email&&(t.error("At least one of phone or email is required"),process.exit(1));let e=await O();c.start("Creating contact...");let n=[];s.phone&&n.push({channel:"SMS",identity:s.phone}),s.email&&n.push({channel:"EMAIL",identity:s.email});let i={contactCreateRequestBody:{channel_identities:n,display_name:s.displayName||s.name,language:"EN_US"}},o=await e.conversation.contact.create(i);c.succeed("Contact created successfully!"),s.json||(t.newline(),t.info(`Contact ID: ${o.id}`),t.info(`Display Name: ${o.display_name||"N/A"}`),s.phone&&t.info(`Phone: ${s.phone}`),s.email&&t.info(`Email: ${s.email}`))}catch(e){c.stop(),t.error(`Failed to create contact: ${e.message}`),e.response?.data&&t.error("API Response:",JSON.stringify(e.response.data,null,2)),e.data&&t.error("Error data:",JSON.stringify(e.data,null,2)),process.exit(1)}});je.command("get").description("Get a specific contact by ID").argument("<contact-id>","Contact ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await O();c.start("Fetching contact...");let i=await n.conversation.contact.get({contact_id:s});c.succeed("Contact retrieved"),e.json?console.log(JSON.stringify(i,null,2)):new Ut(n).showDetails(i)}catch(n){c.stop(),t.error(`Failed to get contact: ${n.message}`),process.exit(1)}});je.command("list").description("List contacts").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").option("--no-interactive","Disable interactive mode").action(async s=>{try{let e=await O();c.start("Fetching contacts...");let n=await e.conversation.contact.list({page_size:s.limit||50}),i=n.data||n.contacts||[];if(c.succeed(`Retrieved ${i.length} contacts`),s.json){console.log(JSON.stringify(n,null,2));return}i&&i.length>0?(t.newline(),t.newline(),s.interactive!==!1?await new Ut(e).runInteractiveList(i):i.forEach(o=>{t.info(o.display_name||"No name"),o.channel_identities&&o.channel_identities.length>0&&o.channel_identities.forEach(r=>{let a=r.channel;a==="CHANNEL_UNSPECIFIED"&&r.identity.includes("@")&&(a="EMAIL"),t.info(`${a}: ${r.identity}`)}),t.newline()})):(t.newline(),t.info("No contacts found"))}catch(e){c.stop(),t.error(`Failed to list contacts: ${e.message}`),process.exit(1)}});je.command("update").description("Update a contact").argument("<contact-id>","Contact ID to update").option("-n, --name <name>","New contact name").option("-d, --display-name <name>","New display name").option("--json","Output result as JSON").action(async(s,e)=>{try{!e.displayName&&!e.name&&(t.error("At least one update field is required (--name or --display-name)"),process.exit(1));let n=await O();c.start("Updating contact...");let i=await n.conversation.contact.update({contact_id:s,display_name:e.displayName||e.name,...e.name&&{metadata:JSON.stringify({name:e.name})}});c.succeed("Contact updated successfully!"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`Contact ID: ${i.id}`),t.info(`Display Name: ${i.display_name||"N/A"}`))}catch(n){c.stop(),t.error(`Failed to update contact: ${n.message}`),process.exit(1)}});je.command("delete").description("Delete a contact").argument("<contact-id>","Contact ID to delete").action(async s=>{try{let e=await O();c.start("Deleting contact..."),await e.conversation.contact.delete({contact_id:s}),c.succeed("Contact deleted successfully")}catch(e){c.stop(),t.error(`Failed to delete contact: ${e.message}`),process.exit(1)}});je.command("merge").description("Merge two contacts").argument("<source-id>","Source contact ID (will be merged into destination)").argument("<dest-id>","Destination contact ID").option("--json","Output result as JSON").action(async(s,e,n)=>{try{let i=await O();c.start("Merging contacts...");let o=await i.conversation.contact.mergeContact({destination_id:e,source_id:s});c.succeed("Contacts merged successfully!"),n.json?console.log(JSON.stringify(o,null,2)):(t.newline(),t.info(`Source contact ${s} merged into ${e}`),t.info(`Result Contact ID: ${o.id}`))}catch(i){c.stop(),t.error(`Failed to merge contacts: ${i.message}`),process.exit(1)}});js.exports=je});var Ts=R((pl,Os)=>{"use strict";var Ns=require("commander");A();E();We();var kt=new Ns.Command("conversations");kt.description("Manage conversations");kt.command("list").description("List conversations").option("-a, --app <app-id>","Filter by Conversation App ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async s=>{try{let e=await O();c.start("Fetching conversations...");let n=await e.conversation.conversation.list({page_size:s.limit||50,...s.app&&{app_id:s.app}});c.succeed(`Retrieved ${n.conversations?.length||0} conversations`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.conversations&&n.conversations.length>0?n.conversations.forEach(i=>{t.info(`[${i.id}]`),t.info(` App ID: ${i.app_id}`),t.info(` Active: ${i.active_channel||"N/A"}`),t.info(` Last Updated: ${i.last_received?new Date(i.last_received).toLocaleString():"N/A"}`),t.newline()}):t.info("No conversations found"))}catch(e){c.stop(),t.error(`Failed to list conversations: ${e.message}`),process.exit(1)}});kt.command("get").description("Get a specific conversation by ID").argument("<conversation-id>","Conversation ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await O();c.start("Fetching conversation...");let i=await n.conversation.conversation.get({conversation_id:s});c.succeed("Conversation retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`Conversation ID: ${i.id}`),t.info(`App ID: ${i.app_id}`),t.info(`Active Channel: ${i.active_channel||"N/A"}`),t.info(`Contact ID: ${i.contact_id||"N/A"}`),i.metadata&&(t.newline(),t.info("Metadata:"),t.info(JSON.stringify(i.metadata,null,2))))}catch(n){c.stop(),t.error(`Failed to get conversation: ${n.message}`),process.exit(1)}});kt.command("stop").description("Stop an active conversation").argument("<conversation-id>","Conversation ID to stop").action(async s=>{try{let e=await O();c.start("Stopping conversation..."),await e.conversation.conversation.delete({conversation_id:s}),c.succeed("Conversation stopped successfully")}catch(e){c.stop(),t.error(`Failed to stop conversation: ${e.message}`),process.exit(1)}});Os.exports=kt});var _s=R((ml,Ls)=>{"use strict";var Fs=require("commander"),An=h(require("inquirer"));A();E();We();var rt=new Fs.Command("apps");rt.description("Manage Conversation apps");rt.command("list").description("List Conversation apps").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async s=>{try{let e=await O();c.start("Fetching apps...");let n=await e.conversation.app.list({page_size:s.limit||50});c.succeed(`Retrieved ${n.apps?.length||0} apps`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.apps&&n.apps.length>0?n.apps.forEach(i=>{t.info(`[${i.id}] ${i.display_name||"No name"}`),t.info(` Channels: ${i.channel_credentials?.length||0} configured`),t.newline()}):t.info("No apps found"))}catch(e){c.stop(),t.error(`Failed to list apps: ${e.message}`),process.exit(1)}});rt.command("get").description("Get a specific Conversation app by ID").argument("<app-id>","App ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await O();c.start("Fetching app...");let i=await n.conversation.app.get({app_id:s});c.succeed("App retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`App ID: ${i.id}`),t.info(`Display Name: ${i.display_name||"N/A"}`),t.info("Rate Limits:",i.rate_limits||"N/A"),i.channel_credentials&&i.channel_credentials.length>0&&(t.newline(),t.info("Configured Channels:"),i.channel_credentials.forEach(o=>{t.info(` - ${o.channel}`)})),i.conversation_metadata_report_view&&(t.newline(),t.info(`Metadata Report: ${i.conversation_metadata_report_view}`)))}catch(n){c.stop(),t.error(`Failed to get app: ${n.message}`),process.exit(1)}});rt.command("create").description("Create a new Conversation app").argument("[name]","App display name").option("--json","Output result as JSON").action(async(s,e)=>{try{s||(s=(await An.default.prompt([{type:"input",name:"name",message:"Enter app display name:",validate:r=>r?!0:"App name is required"}])).name);let n=await O();c.start("Creating app...");let i=await n.conversation.app.create({display_name:s});c.succeed("App created successfully!"),e?.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`App ID: ${i.id}`),t.info(`Display Name: ${i.display_name}`),t.newline(),t.info("\u{1F4A1} Set as default: sinch config set conversation-app-id "+i.id))}catch(n){c.stop(),t.error(`Failed to create app: ${n.message}`),process.exit(1)}});rt.command("delete").description("Delete a Conversation app").argument("<app-id>","App ID to delete").action(async s=>{try{let{confirm:e}=await An.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete app ${s}?`,default:!1}]);if(!e){t.info("Deletion cancelled");return}let n=await O();c.start("Deleting app..."),await n.conversation.app.delete({app_id:s}),c.succeed("App deleted successfully")}catch(e){c.stop(),t.error(`Failed to delete app: ${e.message}`),process.exit(1)}});Ls.exports=rt});var Ms=R((bl,qs)=>{"use strict";var Us=require("commander"),En=h(require("inquirer"));k();A();E();We();var at=new Us.Command("webhooks");at.description("Manage webhooks for Conversation apps");at.command("list").description("List webhooks for a Conversation app").option("-a, --app <app-id>","Conversation App ID").option("--json","Output result as JSON").action(async s=>{try{let e=ot(s.app),n=await O();c.start("Fetching webhooks...");let i=await n.conversation.webhooks.list({app_id:e});c.succeed(`Retrieved ${i.webhooks?.length||0} webhooks`),s.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.webhooks&&i.webhooks.length>0?i.webhooks.forEach(o=>{t.info(`[${o.id}]`),t.info(` URL: ${o.target}`),t.info(` Triggers: ${o.triggers?.join(", ")||"N/A"}`),t.info(` Secret: ${o.secret?"********":"Not set"}`),t.newline()}):t.info("No webhooks found for this app"))}catch(e){c.stop(),t.error(`Failed to list webhooks: ${e.message}`),process.exit(1)}});at.command("create").description("Create a new webhook for a Conversation app").option("-a, --app <app-id>","Conversation App ID").option("-u, --url <url>","Webhook URL").option("-t, --triggers <triggers>","Comma-separated list of triggers (e.g., MESSAGE_INBOUND,MESSAGE_DELIVERY)").option("-s, --secret <secret>","Webhook secret for signature validation").option("--json","Output result as JSON").action(async s=>{try{await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=s.app;if(!n){let a=u.get("conversation-app-id");a&&(n=a,t.info(`Using default app: ${n}`))}if(!n||!s.url||!s.triggers){let a=await En.default.prompt([{type:"input",name:"appId",message:"Enter Conversation App ID:",when:!n,validate:l=>l?!0:"App ID is required"},{type:"input",name:"url",message:"Enter webhook URL:",when:!s.url,validate:l=>{if(!l)return"URL is required";try{return new URL(l),!0}catch{return"Please enter a valid URL"}}},{type:"checkbox",name:"triggers",message:"Select webhook triggers:",when:!s.triggers,choices:["MESSAGE_INBOUND","MESSAGE_DELIVERY","MESSAGE_SUBMIT","EVENT_INBOUND","CONVERSATION_START","CONVERSATION_STOP","CONTACT_CREATE","CONTACT_DELETE","CONTACT_MERGE","CONTACT_UPDATE"],validate:l=>l.length>0?!0:"Select at least one trigger"},{type:"input",name:"secret",message:"Enter webhook secret (optional, press enter to skip):"}]);n=n||a.appId,s.url=s.url||a.url,s.triggers=s.triggers||a.triggers.join(","),s.secret=s.secret||a.secret}let i=await O(),o=s.triggers.split(",").map(a=>a.trim());c.start("Creating webhook...");let r=await i.conversation.webhooks.create({app_id:n,target:s.url,triggers:o,...s.secret&&{secret:s.secret}});c.succeed("Webhook created successfully!"),s.json?console.log(JSON.stringify(r,null,2)):(t.newline(),t.info(`Webhook ID: ${r.id}`),t.info(`URL: ${r.target}`),t.info(`Triggers: ${r.triggers?.join(", ")}`),s.secret&&t.info("Secret: ********"))}catch(e){c.stop(),t.error(`Failed to create webhook: ${e.message}`),process.exit(1)}});at.command("update").description("Update a webhook").argument("<webhook-id>","Webhook ID to update").option("-u, --url <url>","New webhook URL").option("-t, --triggers <triggers>","New comma-separated list of triggers").option("-s, --secret <secret>","New webhook secret").option("--json","Output result as JSON").action(async(s,e)=>{try{!e.url&&!e.triggers&&!e.secret&&(t.error("At least one update field is required (--url, --triggers, or --secret)"),process.exit(1));let n=await O(),i={};e.url&&(i.target=e.url),e.triggers&&(i.triggers=e.triggers.split(",").map(r=>r.trim())),e.secret&&(i.secret=e.secret),c.start("Updating webhook...");let o=await n.conversation.webhooks.update({webhook_id:s,...i});c.succeed("Webhook updated successfully!"),e.json?console.log(JSON.stringify(o,null,2)):(t.newline(),t.info(`Webhook ID: ${o.id}`),t.info(`URL: ${o.target}`),t.info(`Triggers: ${o.triggers?.join(", ")}`))}catch(n){c.stop(),t.error(`Failed to update webhook: ${n.message}`),process.exit(1)}});at.command("delete").description("Delete a webhook").argument("<webhook-id>","Webhook ID to delete").action(async s=>{try{let{confirm:e}=await En.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete webhook ${s}?`,default:!1}]);if(!e){t.info("Deletion cancelled");return}let n=await O();c.start("Deleting webhook..."),await n.conversation.webhooks.delete({webhook_id:s}),c.succeed("Webhook deleted successfully")}catch(e){c.stop(),t.error(`Failed to delete webhook: ${e.message}`),process.exit(1)}});qs.exports=at});var Ks=R((Sl,Bs)=>{"use strict";var Js=require("commander"),Mr=Ps(),Jr=xs(),Br=Rs(),Kr=Ts(),Vr=_s(),Hr=Ms(),Re=new Js.Command("conversation");Re.description("Manage Sinch Conversations API");Re.addCommand(Mr);Re.addCommand(Jr);Re.addCommand(Br);Re.addCommand(Kr);Re.addCommand(Vr);Re.addCommand(Hr);Bs.exports=Re});var xn,Pt,te,Ge=Q(()=>{"use strict";xn=h(require("axios")),Pt=h(require("chalk")),te=class{baseUrl="https://elastic-trunking.api.sinch.com";projectId;credentials;client;timeout=6e4;constructor(e){this.projectId=e.projectId,this.credentials=e.credentials,this.client=xn.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"Content-Type":"application/json","User-Agent":"sinch-functions-cli/1.0.0"}}),this.client.interceptors.request.use(async n=>{let i=await this.getAuthHeader();return i&&(n.headers.Authorization=i),process.env.DEBUG_HTTP&&console.log(Pt.default.gray(`\u2192 ${n.method?.toUpperCase()} ${n.url}`)),n},n=>Promise.reject(n)),this.client.interceptors.response.use(n=>(process.env.DEBUG_HTTP&&console.log(Pt.default.gray(`\u2190 ${n.status} ${n.config.url}`)),n),n=>(process.env.DEBUG_HTTP&&console.log(Pt.default.red(`\u2190 ${n.response?.status||"ERROR"} ${n.config?.url}`)),Promise.reject(n)))}async getAuthHeader(){try{let e=await this.credentials.retrieve();return e&&e.keyId&&e.keySecret?`Basic ${Buffer.from(`${e.keyId}:${e.keySecret}`).toString("base64")}`:null}catch{return console.error(Pt.default.yellow("Failed to get authentication credentials")),null}}async listTrunks(e={}){try{let n={};return e.page&&(n.pageToken=e.page),e.pageSize&&(n.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks`,{params:n})).data}catch(n){throw this.handleError(n,"Failed to list SIP trunks")}}async getTrunk(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}`)).data}catch(n){throw this.handleError(n,`Failed to get SIP trunk ${e}`)}}async createTrunk(e){try{return(await this.client.post(`/v1/projects/${this.projectId}/trunks`,e)).data}catch(n){throw this.handleError(n,"Failed to create SIP trunk")}}async updateTrunk(e,n){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}`,n)).data}catch(i){throw this.handleError(i,`Failed to update SIP trunk ${e}`)}}async deleteTrunk(e){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}`)}catch(n){throw this.handleError(n,`Failed to delete SIP trunk ${e}`)}}async listEndpoints(e,n={}){try{let i={};return n.page&&(i.pageToken=n.page),n.pageSize&&(i.pageSize=n.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/endpoints`,{params:i})).data}catch(i){throw this.handleError(i,`Failed to list endpoints for trunk ${e}`)}}async getEndpoint(e,n){try{return(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${n}`)).data}catch(i){throw this.handleError(i,`Failed to get endpoint ${n}`)}}async createEndpoint(e,n){try{return(await this.client.post(`/v1/projects/${this.projectId}/trunks/${e}/endpoints`,n)).data}catch(i){throw this.handleError(i,"Failed to create SIP endpoint")}}async updateEndpoint(e,n,i){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${n}`,i)).data}catch(o){throw this.handleError(o,`Failed to update endpoint ${n}`)}}async deleteEndpoint(e,n){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${n}`)}catch(i){throw this.handleError(i,`Failed to delete endpoint ${n}`)}}async listAcls(e={}){try{let n={};return e.page&&(n.pageToken=e.page),e.pageSize&&(n.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists`,{params:n})).data}catch(n){throw this.handleError(n,"Failed to list ACLs")}}async getAcl(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}`)).data}catch(n){throw this.handleError(n,`Failed to get ACL ${e}`)}}async createAcl(e){try{return(await this.client.post(`/v1/projects/${this.projectId}/accessControlLists`,e)).data}catch(n){throw this.handleError(n,"Failed to create ACL")}}async updateAcl(e,n){try{return(await this.client.put(`/v1/projects/${this.projectId}/accessControlLists/${e}`,n)).data}catch(i){throw this.handleError(i,`Failed to update ACL ${e}`)}}async deleteAcl(e){try{await this.client.delete(`/v1/projects/${this.projectId}/accessControlLists/${e}`)}catch(n){throw this.handleError(n,`Failed to delete ACL ${e}`)}}async getAclTrunks(e,n={}){try{let i={};return n.page&&(i.pageToken=n.page),n.pageSize&&(i.pageSize=n.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/trunks`,{params:i})).data}catch(i){throw this.handleError(i,`Failed to get trunks for ACL ${e}`)}}async listIpRanges(e,n={}){try{let i={};return n.page&&(i.pageToken=n.page),n.pageSize&&(i.pageSize=n.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges`,{params:i})).data}catch(i){throw this.handleError(i,`Failed to list IP ranges for ACL ${e}`)}}async getIpRange(e,n){try{return(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${n}`)).data}catch(i){throw this.handleError(i,`Failed to get IP range ${n}`)}}async addIpRange(e,n){try{return(await this.client.post(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges`,n)).data}catch(i){throw this.handleError(i,`Failed to add IP range to ACL ${e}`)}}async updateIpRange(e,n,i){try{return(await this.client.put(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${n}`,i)).data}catch(o){throw this.handleError(o,`Failed to update IP range ${n}`)}}async deleteIpRange(e,n){try{await this.client.delete(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${n}`)}catch(i){throw this.handleError(i,`Failed to delete IP range ${n}`)}}async listCountryPermissions(e={}){try{let n={};return e.page&&(n.pageToken=e.page),e.pageSize&&(n.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/countryPermissions`,{params:n})).data}catch(n){throw this.handleError(n,"Failed to list country permissions")}}async getCountryPermission(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/countryPermissions/${e}`)).data}catch(n){throw this.handleError(n,`Failed to get country permission for ${e}`)}}async updateCountryPermission(e,n){try{return(await this.client.put(`/v1/projects/${this.projectId}/countryPermissions/${e}`,{enabled:n})).data}catch(i){throw this.handleError(i,`Failed to update country permission for ${e}`)}}async listTrunkAcls(e,n={}){try{let i={};return n.page&&(i.pageToken=n.page),n.pageSize&&(i.pageSize=n.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists`,{params:i})).data}catch(i){throw this.handleError(i,`Failed to list ACLs for trunk ${e}`)}}async addTrunkAcl(e,n){try{await this.client.post(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists`,{accessControlListId:n})}catch(i){throw this.handleError(i,`Failed to add ACL ${n} to trunk ${e}`)}}async removeTrunkAcl(e,n){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists/${n}`)}catch(i){throw this.handleError(i,`Failed to remove ACL ${n} from trunk ${e}`)}}async getCredentialListTrunks(e,n={}){try{let i={};return n.page&&(i.pageNumber=n.page),n.pageSize&&(i.pageSize=n.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/credentialLists/${e}/trunks`,{params:i})).data}catch(i){throw this.handleError(i,`Failed to get trunks for credential list ${e}`)}}async updateTrunkCredentialLists(e,n){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}/credentialLists`,{credentialListIds:n})).data}catch(i){throw this.handleError(i,`Failed to update credential lists for trunk ${e}`)}}async findCalls(e={}){try{let n={};return e.from&&(n.from=e.from),e.to&&(n.to=e.to),e.trunkId&&(n.trunkId=e.trunkId),e.createTime&&(n.createTime=e.createTime),e.callResult&&(n.callResult=e.callResult),e.direction&&(n.direction=e.direction),e.page&&(n.pageNumber=e.page),e.pageSize&&(n.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/calls`,{params:n})).data}catch(n){throw this.handleError(n,"Failed to find calls")}}async getCall(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/calls/${e}`)).data}catch(n){throw this.handleError(n,`Failed to get call ${e}`)}}handleError(e,n){if(xn.default.isAxiosError(e)){let i=e;if(i.response){let o=i.response.status,r=i.response.data,a=r?.message||r?.error||i.message;throw o===401?new Error('Authentication required. Please run "sinch auth login" first.'):o===403?new Error(`Permission denied: ${a}`):o===404?new Error(`Resource not found: ${a}`):o>=500?new Error(`Server error: ${a}`):new Error(`${n}: ${a}`)}else throw i.request?i.code==="ECONNREFUSED"?new Error(`Cannot connect to EST API at ${this.baseUrl}`):i.code==="ETIMEDOUT"?new Error(`Request timeout after ${this.timeout}ms`):new Error(`${n}: No response from server (${i.code||"unknown error"})`):new Error(`${n}: ${i.message}`)}else throw new Error(`${n}: ${e.message||e}`)}}});var Hs=R((Dl,Vs)=>{"use strict";var qt=require("commander"),be=h(require("inquirer"));A();E();k();Ge();async function Se(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}function Dn(s){t.info(`ID: ${s.id}`),t.info(`Name: ${s.name}`),s.hostName&&t.info(`Host: ${s.hostName}`),t.info(`Caller ID: ${s.enableCallerId?"enabled":"disabled"}`),s.createTime&&t.info(`Created: ${new Date(s.createTime).toLocaleString()}`),s.updateTime&&t.info(`Updated: ${new Date(s.updateTime).toLocaleString()}`)}var ve=new qt.Command("trunks");ve.description("Manage SIP trunks");ve.command("list").description("List all SIP trunks").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async s=>{try{let e=await Se();c.start("Fetching SIP trunks...");let n=await e.listTrunks({pageSize:s.limit});c.succeed(`Retrieved ${n.trunks?.length||0} trunk(s)`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.trunks&&n.trunks.length>0?n.trunks.forEach(i=>{t.info(`[${i.id}] ${i.name}`),i.hostName&&t.info(` Host: ${i.hostName}`),t.info(` Caller ID: ${i.enableCallerId?"enabled":"disabled"}`),t.newline()}):(t.info("No SIP trunks found"),t.newline(),t.info("Create one with: sinch sip trunks create")))}catch(e){c.stop(),t.error(`Failed to list trunks: ${e.message}`),process.exit(1)}});ve.command("get").description("Get a SIP trunk by ID").argument("<trunk-id>","Trunk ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Se();c.start("Fetching trunk...");let i=await n.getTrunk(s);c.succeed("Trunk retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Dn(i))}catch(n){c.stop(),t.error(`Failed to get trunk: ${n.message}`),process.exit(1)}});ve.command("create").description("Create a new SIP trunk").option("-n, --name <name>","Trunk name (required)").option("-h, --host-name <hostname>","Host name for the trunk (required)").option("--caller-id","Enable caller ID").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async s=>{try{let e=s.name,n=s.hostName,i=s.callerId??!1,o=!s.nonInteractive;e||(o?e=(await be.default.prompt([{type:"input",name:"name",message:"Enter trunk name:",validate:p=>p?!0:"Trunk name is required"}])).name:(t.error("Name is required. Use --name <name>"),process.exit(1))),n||(o?n=(await be.default.prompt([{type:"input",name:"hostName",message:"Enter host name:",validate:p=>p?!0:"Host name is required"}])).hostName:(t.error("Host name is required. Use --host-name <hostname>"),process.exit(1))),s.callerId===void 0&&o&&(i=(await be.default.prompt([{type:"confirm",name:"enableCallerId",message:"Enable caller ID?",default:!1}])).enableCallerId);let r=await Se();c.start("Creating SIP trunk...");let a=await r.createTrunk({name:e,hostName:n,enableCallerId:i});c.succeed("SIP trunk created successfully!"),s.json?console.log(JSON.stringify(a,null,2)):(t.newline(),Dn(a),t.newline(),t.info(`Add an endpoint: sinch sip endpoints create ${a.id}`))}catch(e){c.stop(),t.error(`Failed to create trunk: ${e.message}`),process.exit(1)}});ve.command("update").description("Update a SIP trunk").argument("<trunk-id>","Trunk ID to update").option("-n, --name <name>","New trunk name").option("-h, --host-name <hostname>","New host name").option("--caller-id","Enable caller ID").option("--no-caller-id","Disable caller ID").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Se();c.start("Fetching current trunk details...");let i=await n.getTrunk(s);c.stop();let o=e.name,r=e.hostName,a=e.callerId,l=!e.nonInteractive;o||(l?o=(await be.default.prompt([{type:"input",name:"name",message:"Enter trunk name:",default:i.name,validate:f=>f?!0:"Trunk name is required"}])).name:o=i.name),r===void 0&&(l?r=(await be.default.prompt([{type:"input",name:"hostName",message:"Enter host name:",default:i.hostName||""}])).hostName||void 0:r=i.hostName),a===void 0&&(l?a=(await be.default.prompt([{type:"confirm",name:"enableCallerId",message:"Enable caller ID?",default:i.enableCallerId??!1}])).enableCallerId:a=i.enableCallerId),c.start("Updating SIP trunk...");let p=await n.updateTrunk(s,{name:o,hostName:r,enableCallerId:a});c.succeed("SIP trunk updated successfully!"),e.json?console.log(JSON.stringify(p,null,2)):(t.newline(),Dn(p))}catch(n){c.stop(),t.error(`Failed to update trunk: ${n.message}`),process.exit(1)}});ve.command("delete").description("Delete a SIP trunk").argument("<trunk-id>","Trunk ID to delete").option("-f, --force","Skip confirmation prompt").action(async(s,e)=>{try{if(!e.force){let{confirm:i}=await be.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete trunk ${s}?`,default:!1}]);if(!i){t.info("Deletion cancelled");return}}let n=await Se();c.start("Deleting SIP trunk..."),await n.deleteTrunk(s),c.succeed("SIP trunk deleted successfully")}catch(n){c.stop(),t.error(`Failed to delete trunk: ${n.message}`),process.exit(1)}});var At=new qt.Command("acls");At.description("Manage ACLs for a trunk");At.command("list").description("List ACLs associated with a trunk").argument("<trunk-id>","Trunk ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Se();c.start("Fetching trunk ACLs...");let i=await n.listTrunkAcls(s,{pageSize:e.limit});c.succeed(`Retrieved ${i.accessControlLists?.length||0} ACL(s)`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.accessControlLists&&i.accessControlLists.length>0?i.accessControlLists.forEach(o=>{let r=o.enabled!==!1?"":" (disabled)";t.info(`[${o.id}] ${o.name}${r}`),t.newline()}):(t.info("No ACLs associated with this trunk"),t.newline(),t.info(`Add an ACL: sinch sip trunks acls add ${s} <acl-id>`)))}catch(n){c.stop(),t.error(`Failed to list trunk ACLs: ${n.message}`),process.exit(1)}});At.command("add").description("Add an ACL to a trunk").argument("<trunk-id>","Trunk ID").argument("<acl-id>","ACL ID to add").option("--json","Output result as JSON").action(async(s,e,n)=>{try{let i=await Se();c.start(`Adding ACL ${e} to trunk ${s}...`),await i.addTrunkAcl(s,e),c.succeed("ACL added to trunk successfully"),n.json||(t.newline(),t.info(`ACL ${e} is now associated with trunk ${s}`))}catch(i){c.stop(),t.error(`Failed to add ACL to trunk: ${i.message}`),process.exit(1)}});At.command("remove").description("Remove an ACL from a trunk").argument("<trunk-id>","Trunk ID").argument("<acl-id>","ACL ID to remove").option("-f, --force","Skip confirmation prompt").action(async(s,e,n)=>{try{if(!n.force){let{confirm:o}=await be.default.prompt([{type:"confirm",name:"confirm",message:`Remove ACL ${e} from trunk ${s}?`,default:!1}]);if(!o){t.info("Operation cancelled");return}}let i=await Se();c.start("Removing ACL from trunk..."),await i.removeTrunkAcl(s,e),c.succeed("ACL removed from trunk successfully")}catch(i){c.stop(),t.error(`Failed to remove ACL from trunk: ${i.message}`),process.exit(1)}});ve.addCommand(At);var jn=new qt.Command("credential-lists");jn.description("Manage credential lists for a trunk");jn.command("update").description("Bulk update credential lists for a trunk").argument("<trunk-id>","Trunk ID").argument("<credential-list-ids...>","Credential list IDs to assign (space-separated)").option("--json","Output result as JSON").action(async(s,e,n)=>{try{let i=await Se();c.start(`Updating credential lists for trunk ${s}...`);let o=await i.updateTrunkCredentialLists(s,e);if(c.succeed("Credential lists updated successfully"),n.json)console.log(JSON.stringify(o,null,2));else{t.newline();let r=o?.credentialListIds??[];t.info(`Trunk ${s} now uses ${r.length} credential list(s):`),r.forEach(a=>{t.info(` - ${a}`)})}}catch(i){c.stop(),t.error(`Failed to update credential lists: ${i.message}`),process.exit(1)}});ve.addCommand(jn);Vs.exports=ve});var Gs=R((Fl,Ws)=>{"use strict";var zs=require("commander"),he=h(require("inquirer"));A();E();k();Ge();async function Et(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}async function Rn(s,e){c.start("Looking up endpoint...");let i=(await s.listTrunks()).trunks||[];for(let o of i)if(((await s.listEndpoints(o.id)).endpoints||[]).find(p=>p.id===e))return c.stop(),o.id;throw c.stop(),new Error(`Endpoint ${e} not found`)}function Nn(s){if(t.info(`ID: ${s.id}`),t.info(`Name: ${s.name}`),s.address){let e=s.port?`${s.address}:${s.port}`:s.address;t.info(`Address: ${e}`)}s.transport&&t.info(`Transport: ${s.transport}`),t.info(`Priority: ${s.priority}`),t.info(`Enabled: ${s.enabled!==!1?"yes":"no"}`),s.createTime&&t.info(`Created: ${new Date(s.createTime).toLocaleString()}`),s.updateTime&&t.info(`Updated: ${new Date(s.updateTime).toLocaleString()}`)}var Ye=new zs.Command("endpoints");Ye.description("Manage SIP endpoints");Ye.command("list").description("List all SIP endpoints for a trunk").argument("<trunk-id>","Trunk ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Et();c.start("Fetching SIP endpoints...");let i=await n.listEndpoints(s,{pageSize:e.limit});c.succeed(`Retrieved ${i.endpoints?.length||0} endpoint(s)`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.endpoints&&i.endpoints.length>0?i.endpoints.forEach(o=>{let r=o.enabled!==!1?"":" (disabled)",a=o.port?`${o.address}:${o.port}`:o.address;t.info(`[${o.id}] ${o.name}${r}`),t.info(` Address: ${a||"N/A"}`),t.info(` Priority: ${o.priority}, Transport: ${o.transport||"UDP"}`),t.newline()}):(t.info("No endpoints found for this trunk"),t.newline(),t.info(`Create one with: sinch sip endpoints create ${s}`)))}catch(n){c.stop(),t.error(`Failed to list endpoints: ${n.message}`),process.exit(1)}});Ye.command("get").description("Get a SIP endpoint by ID").argument("<endpoint-id>","Endpoint ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Et(),i=await Rn(n,s);c.start("Fetching endpoint...");let o=await n.getEndpoint(i,s);c.succeed("Endpoint retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(t.newline(),Nn(o))}catch(n){c.stop(),t.error(`Failed to get endpoint: ${n.message}`),process.exit(1)}});Ye.command("create").description("Create a new SIP endpoint").argument("<trunk-id>","Trunk ID to add endpoint to").option("-n, --name <name>","Endpoint name (required)").option("-a, --address <address>","SIP address (IP or hostname, without port)").option("--port <number>","SIP port (default: 5060)",parseInt).option("-t, --transport <transport>","Transport protocol: UDP, TCP, or TLS (default: UDP)").option("-p, --priority <number>","Priority (required, lower = higher priority)",parseInt).option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=e.name,i=e.address,o=e.port,r=e.transport,a=e.priority,l=!e.nonInteractive;n||(l?n=(await he.default.prompt([{type:"input",name:"name",message:"Enter endpoint name:",validate:g=>g?!0:"Endpoint name is required"}])).name:(t.error("Name is required. Use --name <name>"),process.exit(1))),i||(l?i=(await he.default.prompt([{type:"input",name:"address",message:"Enter SIP address (IP or hostname):",validate:g=>g?!0:"SIP address is required"}])).address:(t.error("Address is required. Use --address <address>"),process.exit(1))),o===void 0&&l&&(o=(await he.default.prompt([{type:"input",name:"port",message:"Enter SIP port (default 5060):",default:"5060",filter:g=>g?parseInt(g,10):5060}])).port),a===void 0&&(l?a=(await he.default.prompt([{type:"input",name:"priority",message:"Enter priority (lower = higher priority):",default:"1",filter:g=>parseInt(g,10),validate:g=>{let w=parseInt(g,10);return isNaN(w)?"Please enter a valid number":!0}}])).priority:(t.error("Priority is required. Use --priority <number>"),process.exit(1)));let p=await Et();c.start("Creating SIP endpoint...");let d=await p.createEndpoint(s,{name:n,address:i,port:o,transport:r,priority:a});c.succeed("SIP endpoint created successfully!"),e.json?console.log(JSON.stringify(d,null,2)):(t.newline(),Nn(d))}catch(n){c.stop(),t.error(`Failed to create endpoint: ${n.message}`),process.exit(1)}});Ye.command("update").description("Update a SIP endpoint").argument("<endpoint-id>","Endpoint ID to update").option("-n, --name <name>","New endpoint name").option("-a, --address <address>","New SIP address").option("--port <number>","New SIP port",parseInt).option("-t, --transport <transport>","Transport protocol: UDP, TCP, or TLS").option("-p, --priority <number>","New priority",parseInt).option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Et(),i=await Rn(n,s);c.start("Fetching current endpoint details...");let o=await n.getEndpoint(i,s);c.stop();let r=e.name,a=e.address,l=e.port,p=e.transport,d=e.priority,f=!e.nonInteractive;r||(f?r=(await he.default.prompt([{type:"input",name:"name",message:"Enter endpoint name:",default:o.name,validate:y=>y?!0:"Name is required"}])).name:r=o.name),a||(f?a=(await he.default.prompt([{type:"input",name:"address",message:"Enter SIP address:",default:o.address,validate:y=>y?!0:"SIP address is required"}])).address:a=o.address||""),l===void 0&&(f?l=(await he.default.prompt([{type:"input",name:"port",message:"Enter SIP port:",default:(o.port||5060).toString(),filter:y=>parseInt(y,10)}])).port:l=o.port),d===void 0&&(f?d=(await he.default.prompt([{type:"input",name:"priority",message:"Enter priority:",default:o.priority.toString(),filter:y=>parseInt(y,10)}])).priority:d=o.priority),c.start("Updating SIP endpoint...");let g=await n.updateEndpoint(i,s,{name:r,address:a,port:l,transport:p,priority:d});c.succeed("SIP endpoint updated successfully!"),e.json?console.log(JSON.stringify(g,null,2)):(t.newline(),Nn(g))}catch(n){c.stop(),t.error(`Failed to update endpoint: ${n.message}`),process.exit(1)}});Ye.command("delete").description("Delete a SIP endpoint").argument("<endpoint-id>","Endpoint ID to delete").option("-f, --force","Skip confirmation prompt").action(async(s,e)=>{try{let n=await Et(),i=await Rn(n,s);if(!e.force){let{confirm:o}=await he.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete endpoint ${s}?`,default:!1}]);if(!o){t.info("Deletion cancelled");return}}c.start("Deleting SIP endpoint..."),await n.deleteEndpoint(i,s),c.succeed("SIP endpoint deleted successfully")}catch(n){c.stop(),t.error(`Failed to delete endpoint: ${n.message}`),process.exit(1)}});Ws.exports=Ye});var Qs=R((Bl,Zs)=>{"use strict";var On=require("commander"),K=h(require("inquirer"));A();E();k();Ge();async function ye(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}function Tn(s){t.info(`ID: ${s.id}`),t.info(`Name: ${s.name}`),t.info(`Enabled: ${s.enabled!==!1?"yes":"no"}`),s.createTime&&t.info(`Created: ${new Date(s.createTime).toLocaleString()}`),s.updateTime&&t.info(`Updated: ${new Date(s.updateTime).toLocaleString()}`)}function Ys(s){t.info(`ID: ${s.id}`),s.description&&t.info(`Description: ${s.description}`),s.ipAddress&&t.info(`IP Address: ${s.ipAddress}`),s.range&&t.info(`CIDR Range: ${s.range}`),s.createTime&&t.info(`Created: ${new Date(s.createTime).toLocaleString()}`)}function Ze(s){return/^(\d{1,3}\.){3}\d{1,3}$/.test(s)?s.split(".").every(i=>{let o=parseInt(i,10);return o>=0&&o<=255}):!1}function Mt(s){if(!/^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/.test(s))return!1;let n=s.split("/");if(n.length!==2)return!1;let i=n[0],o=n[1];if(!i||!o)return!1;let r=parseInt(o,10);return Ze(i)&&r>=0&&r<=32}var $e=new On.Command("acls");$e.description("Manage Access Control Lists (ACLs)");$e.command("list").description("List all Access Control Lists").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async s=>{try{let e=await ye();c.start("Fetching ACLs...");let n=await e.listAcls({pageSize:s.limit});c.succeed(`Retrieved ${n.accessControlLists?.length||0} ACL(s)`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.accessControlLists&&n.accessControlLists.length>0?n.accessControlLists.forEach(i=>{let o=i.enabled!==!1?"":" (disabled)";t.info(`[${i.id}] ${i.name}${o}`),t.newline()}):(t.info("No ACLs found"),t.newline(),t.info("Create one with: sinch sip acls create")))}catch(e){c.stop(),t.error(`Failed to list ACLs: ${e.message}`),process.exit(1)}});$e.command("get").description("Get an ACL by ID").argument("<acl-id>","ACL ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await ye();c.start("Fetching ACL...");let i=await n.getAcl(s);c.succeed("ACL retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Tn(i))}catch(n){c.stop(),t.error(`Failed to get ACL: ${n.message}`),process.exit(1)}});$e.command("create").description("Create a new Access Control List").option("-n, --name <name>","ACL name (required)").option("--enabled","Enable the ACL (default: true)").option("--disabled","Create ACL in disabled state").option("-i, --ip <address>","IP address for initial IP range (required)").option("-r, --range <cidr>","CIDR mask for IP range (default: 32)",parseInt).option("--ip-description <text>","Description for the IP range").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async s=>{try{let e=s.name,n=s.enabled??!s.disabled,i=s.ip,o=s.range,r=s.ipDescription,a=!s.nonInteractive;e||(a?e=(await K.default.prompt([{type:"input",name:"name",message:"Enter ACL name:",validate:g=>g?!0:"ACL name is required"}])).name:(t.error("Name is required. Use --name <name>"),process.exit(1))),s.enabled===void 0&&!s.disabled&&a&&(n=(await K.default.prompt([{type:"confirm",name:"enabled",message:"Enable ACL?",default:!0}])).enabled),i?Ze(i)||(t.error(`Invalid IP address format: ${i}`),process.exit(1)):a?i=(await K.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address for initial IP range (required):",validate:g=>g?Ze(g)?!0:"Invalid IP address format":"At least one IP range is required to create an ACL"}])).ipAddress:(t.error("IP address is required. Use --ip <address>"),process.exit(1)),o===void 0&&a&&(o=(await K.default.prompt([{type:"input",name:"range",message:"Enter CIDR mask (default 32):",default:"32",filter:g=>parseInt(g,10),validate:g=>{let w=parseInt(g,10);return!isNaN(w)&&w>=0&&w<=32?!0:"Please enter a number between 0 and 32"}}])).range),r===void 0&&a&&(r=(await K.default.prompt([{type:"input",name:"description",message:"Enter IP range description (optional):"}])).description||void 0);let l=await ye(),p={ipAddress:i};o!==void 0&&(p.range=o),r&&(p.description=r),c.start("Creating ACL...");let d=await l.createAcl({name:e,enabled:n,ipRanges:[p]});c.succeed("ACL created successfully!"),s.json?console.log(JSON.stringify(d,null,2)):(t.newline(),Tn(d),t.newline(),t.info(`Add an IP range: sinch sip acls ip-ranges add ${d.id}`))}catch(e){c.stop(),t.error(`Failed to create ACL: ${e.message}`),process.exit(1)}});$e.command("update").description("Update an ACL").argument("<acl-id>","ACL ID to update").option("-n, --name <name>","New ACL name").option("--enabled","Enable the ACL").option("--disabled","Disable the ACL").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await ye();c.start("Fetching current ACL details...");let i=await n.getAcl(s);c.stop();let o=e.name,r;e.enabled?r=!0:e.disabled&&(r=!1);let a=!e.nonInteractive;o||(a?o=(await K.default.prompt([{type:"input",name:"name",message:"Enter ACL name:",default:i.name,validate:d=>d?!0:"ACL name is required"}])).name:o=i.name),r===void 0&&(a?r=(await K.default.prompt([{type:"confirm",name:"enabled",message:"Enable ACL?",default:i.enabled??!0}])).enabled:r=i.enabled),c.start("Updating ACL...");let l=await n.updateAcl(s,{name:o,enabled:r});c.succeed("ACL updated successfully!"),e.json?console.log(JSON.stringify(l,null,2)):(t.newline(),Tn(l))}catch(n){c.stop(),t.error(`Failed to update ACL: ${n.message}`),process.exit(1)}});$e.command("delete").description("Delete an ACL").argument("<acl-id>","ACL ID to delete").option("-f, --force","Skip confirmation prompt").action(async(s,e)=>{try{if(!e.force){let{confirm:i}=await K.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete ACL ${s}?`,default:!1}]);if(!i){t.info("Deletion cancelled");return}}let n=await ye();c.start("Deleting ACL..."),await n.deleteAcl(s),c.succeed("ACL deleted successfully")}catch(n){c.stop(),t.error(`Failed to delete ACL: ${n.message}`),process.exit(1)}});$e.command("trunks").description("List trunks using an ACL").argument("<acl-id>","ACL ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await ye();c.start("Fetching trunks...");let i=await n.getAclTrunks(s,{pageSize:e.limit});c.succeed(`Retrieved ${i.trunks?.length||0} trunk(s)`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.trunks&&i.trunks.length>0?i.trunks.forEach(o=>{t.info(`[${o.id}] ${o.name}`),o.hostName&&t.info(` Host: ${o.hostName}`),t.newline()}):t.info("No trunks are using this ACL"))}catch(n){c.stop(),t.error(`Failed to list trunks: ${n.message}`),process.exit(1)}});var ct=new On.Command("ip-ranges");ct.description("Manage IP ranges for ACLs");ct.command("list").description("List IP ranges for an ACL").argument("<acl-id>","ACL ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await ye();c.start("Fetching IP ranges...");let i=await n.listIpRanges(s,{pageSize:e.limit});c.succeed(`Retrieved ${i.ipRanges?.length||0} IP range(s)`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.ipRanges&&i.ipRanges.length>0?i.ipRanges.forEach(o=>{let r=o.range||o.ipAddress||"N/A";t.info(`[${o.id}] ${r}`),o.description&&t.info(` ${o.description}`),t.newline()}):(t.info("No IP ranges found for this ACL"),t.newline(),t.info(`Add one with: sinch sip acls ip-ranges add ${s}`)))}catch(n){c.stop(),t.error(`Failed to list IP ranges: ${n.message}`),process.exit(1)}});ct.command("add").description("Add an IP range to an ACL").argument("<acl-id>","ACL ID").option("-d, --description <description>","Description for the IP range").option("-i, --ip <ip>","Single IP address (e.g., 192.168.1.1)").option("-r, --range <cidr>","CIDR range (e.g., 192.168.1.0/24)").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=e.description,i=e.ip,o=e.range,r=!e.nonInteractive;i&&o&&(t.error("Cannot specify both --ip and --range. Please provide only one."),process.exit(1)),!i&&!o&&(r?(await K.default.prompt([{type:"list",name:"type",message:"What would you like to add?",choices:[{name:"Single IP address",value:"ip"},{name:"CIDR range",value:"range"}]}])).type==="ip"?i=(await K.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address (e.g., 192.168.1.1):",validate:g=>g?Ze(g)?!0:"Invalid IP address format":"IP address is required"}])).ipAddress:o=(await K.default.prompt([{type:"input",name:"range",message:"Enter CIDR range (e.g., 192.168.1.0/24):",validate:g=>g?Mt(g)?!0:"Invalid CIDR format (e.g., 192.168.1.0/24)":"CIDR range is required"}])).range:(t.error("Either --ip or --range is required"),process.exit(1))),i&&!Ze(i)&&(t.error(`Invalid IP address format: ${i}`),process.exit(1)),o&&!Mt(o)&&(t.error(`Invalid CIDR range format: ${o}. Expected format: 192.168.1.0/24`),process.exit(1)),!n&&r&&(n=(await K.default.prompt([{type:"input",name:"description",message:"Enter description (optional):"}])).description||void 0);let a=await ye();c.start("Adding IP range...");let l={description:n};i?l.ipAddress=i:o&&(l.range=o);let p=await a.addIpRange(s,l);c.succeed("IP range added successfully!"),e.json?console.log(JSON.stringify(p,null,2)):(t.newline(),Ys(p))}catch(n){c.stop(),t.error(`Failed to add IP range: ${n.message}`),process.exit(1)}});ct.command("update").description("Update an IP range").argument("<acl-id>","ACL ID").argument("<ip-range-id>","IP range ID to update").option("-d, --description <description>","New description").option("-i, --ip <ip>","New single IP address").option("-r, --range <cidr>","New CIDR range").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(s,e,n)=>{try{let i=await ye();c.start("Fetching current IP range details...");let o;try{o=await i.getIpRange(s,e)}catch(g){c.stop(),t.error(`IP range ${e} not found in ACL ${s}: ${g.message}`),process.exit(1)}c.stop();let r=n.description,a=n.ip,l=n.range,p=!n.nonInteractive;if(a&&l&&(t.error("Cannot specify both --ip and --range. Please provide only one."),process.exit(1)),r===void 0&&p?r=(await K.default.prompt([{type:"input",name:"description",message:"Enter description:",default:o.description||""}])).description||void 0:r===void 0&&(r=o.description),!a&&!l&&p){let g=o.range||o.ipAddress||"",w=o.range?"range":"ip";(await K.default.prompt([{type:"list",name:"type",message:"Update as:",choices:[{name:"Single IP address",value:"ip"},{name:"CIDR range",value:"range"}],default:w}])).type==="ip"?(a=(await K.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address:",default:w==="ip"?g:"",validate:$=>$?Ze($)?!0:"Invalid IP address format":"IP address is required"}])).ipAddress,l=void 0):(l=(await K.default.prompt([{type:"input",name:"range",message:"Enter CIDR range:",default:w==="range"?g:"",validate:$=>$?Mt($)?!0:"Invalid CIDR format":"CIDR range is required"}])).range,a=void 0)}else!a&&!l?(a=o.ipAddress,l=o.range):a?l=void 0:l&&(a=void 0);a&&!Ze(a)&&(t.error(`Invalid IP address format: ${a}`),process.exit(1)),l&&!Mt(l)&&(t.error(`Invalid CIDR range format: ${l}`),process.exit(1)),c.start("Updating IP range...");let d={description:r};a?d.ipAddress=a:l&&(d.range=l);let f=await i.updateIpRange(s,e,d);c.succeed("IP range updated successfully!"),n.json?console.log(JSON.stringify(f,null,2)):(t.newline(),Ys(f))}catch(i){c.stop(),t.error(`Failed to update IP range: ${i.message}`),process.exit(1)}});ct.command("delete").description("Delete an IP range").argument("<acl-id>","ACL ID").argument("<ip-range-id>","IP range ID to delete").option("-f, --force","Skip confirmation prompt").action(async(s,e,n)=>{try{if(!n.force){let{confirm:o}=await K.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete IP range ${e}?`,default:!1}]);if(!o){t.info("Deletion cancelled");return}}let i=await ye();c.start("Deleting IP range..."),await i.deleteIpRange(s,e),c.succeed("IP range deleted successfully")}catch(i){c.stop(),t.error(`Failed to delete IP range: ${i.message}`),process.exit(1)}});$e.addCommand(ct);Zs.exports=$e});var to=R((Gl,eo)=>{"use strict";var Xs=require("commander");A();E();k();Ge();async function Jt(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}function Fn(s){t.info(`ISO Code: ${s.isoCode}`),t.info(`Country: ${s.name}`),t.info(`Continent: ${s.continent}`),t.info(`Dialing Codes: ${s.countryDialingCodes.join(", ")}`),t.info(`Status: ${s.enabled?"enabled":"disabled"}`)}var lt=new Xs.Command("countries");lt.description("Manage country permissions for dialing");lt.command("list").description("List all country permissions").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async s=>{try{let e=await Jt();c.start("Fetching country permissions...");let n=await e.listCountryPermissions({pageSize:s.limit});c.succeed(`Retrieved ${n.countryPermissions?.length||0} country permission(s)`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.countryPermissions&&n.countryPermissions.length>0?([...n.countryPermissions].sort((o,r)=>o.isoCode.localeCompare(r.isoCode)).forEach(o=>{let r=o.enabled?"\u2713 enabled":"\u2717 disabled",a=o.name.padEnd(30);t.info(`${o.isoCode.padEnd(4)} ${a} ${r}`)}),t.newline(),t.info("Enable a country: sinch sip countries enable <iso-code>"),t.info("Disable a country: sinch sip countries disable <iso-code>")):t.info("No country permissions found"))}catch(e){c.stop(),t.error(`Failed to list country permissions: ${e.message}`),process.exit(1)}});lt.command("get").description("Get a specific country permission by ISO code").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Jt();c.start("Fetching country permission...");let i=await n.getCountryPermission(s.toUpperCase());c.succeed("Country permission retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Fn(i))}catch(n){c.stop(),t.error(`Failed to get country permission: ${n.message}`),process.exit(1)}});lt.command("enable").description("Enable a country for dialing").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Jt();c.start(`Enabling country ${s.toUpperCase()}...`);let i=await n.updateCountryPermission(s.toUpperCase(),!0);c.succeed(`Country ${s.toUpperCase()} enabled for dialing`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Fn(i),t.newline(),t.info(`Country ${s.toUpperCase()} is now enabled for dialing`))}catch(n){c.stop(),t.error(`Failed to enable country: ${n.message}`),process.exit(1)}});lt.command("disable").description("Disable a country for dialing").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Jt();c.start(`Disabling country ${s.toUpperCase()}...`);let i=await n.updateCountryPermission(s.toUpperCase(),!1);c.succeed(`Country ${s.toUpperCase()} disabled for dialing`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Fn(i),t.newline(),t.info(`Country ${s.toUpperCase()} is now disabled for dialing`))}catch(n){c.stop(),t.error(`Failed to disable country: ${n.message}`),process.exit(1)}});eo.exports=lt});var so=R((td,io)=>{"use strict";var no=require("commander");A();E();k();Ge();async function zr(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}var Ln=new no.Command("credential-lists");Ln.description("Manage credential list relationships");Ln.command("trunks").description("Get trunks using a credential list").argument("<credential-list-id>","Credential list ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await zr();c.start("Fetching trunks using credential list...");let i=await n.getCredentialListTrunks(s,{pageSize:e.limit});c.succeed(`Retrieved ${i.trunks?.length||0} trunk(s)`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.trunks&&i.trunks.length>0?(t.info(`Trunks using credential list ${s}:`),t.newline(),i.trunks.forEach(o=>{t.info(`[${o.id}] ${o.name}`),o.hostName&&t.info(` Host: ${o.hostName}`),t.info(` Caller ID: ${o.enableCallerId?"enabled":"disabled"}`),t.newline()}),i.totalItems&&t.info(`Total: ${i.totalItems} trunk(s)`)):t.info("No trunks found using this credential list"))}catch(n){c.stop(),t.error(`Failed to get trunks for credential list: ${n.message}`),process.exit(1)}});io.exports=Ln});var co=R((ld,xt)=>{"use strict";var oo=require("commander");A();E();k();Ge();async function ro(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}function ao(s){if(!s){let n=new Date;return`>=${new Date(n.getTime()-1440*60*1e3).toISOString()}`}if(s.startsWith(">=")||s.startsWith("<=")||s.startsWith(">")||s.startsWith("<"))return s;let e=s.split("-");if(e.length===1&&e[0]){let n=e[0];return`>=${n}-01-01T00:00:00Z,<=${n}-12-31T23:59:59Z`}else if(e.length===2&&e[0]&&e[1]){let n=e[0],i=e[1],o=new Date(parseInt(n),parseInt(i),0).getDate();return`>=${n}-${i}-01T00:00:00Z,<=${n}-${i}-${o.toString().padStart(2,"0")}T23:59:59Z`}else return`>=${s}T00:00:00Z,<=${s}T23:59:59Z`}function Bt(s){if(s===void 0||s===0)return"-";let e=Math.floor(s/3600),n=Math.floor(s%3600/60),i=s%60;return e>0?`${e}h ${n}m ${i}s`:n>0?`${n}m ${i}s`:`${i}s`}function _n(s){return!s||!s.amount?"-":`${parseFloat(s.amount).toFixed(4)} ${s.currencyCode}`}function Wr(s,e=!1){t.info(`Call ID: ${s.callId}`),t.info(`From: ${s.from}`),t.info(`To: ${s.to}`),t.info(`Direction: ${s.direction}`),t.info(`Status: ${s.callResult||"In Progress"}`),(e||s.durationSeconds)&&t.info(`Duration: ${Bt(s.durationSeconds)}`),(e||s.billingDurationSeconds)&&t.info(`Billing Duration: ${Bt(s.billingDurationSeconds)}`),s.price&&t.info(`Cost: ${_n(s.price)}`),t.info(`Trunk ID: ${s.trunkId}`),t.info(`Created: ${new Date(s.createTime).toLocaleString()}`),s.answerTime&&t.info(`Answered: ${new Date(s.answerTime).toLocaleString()}`),s.endTime&&t.info(`Ended: ${new Date(s.endTime).toLocaleString()}`)}var Kt=new oo.Command("calls");Kt.description("View call history and details");Kt.command("list").description("List calls with filtering options").option("--from <number>","Filter by originating phone number (supports partial matching)").option("--to <number>","Filter by destination phone number (supports partial matching)").option("--trunk-id <id>","Filter by trunk ID").option("--direction <direction>","Filter by direction (INBOUND or OUTBOUND)").option("--result <result>","Filter by call result (COMPLETED, NO_ANSWER, CANCEL, BUSY, FAILED)").option("--date <date>","Filter by date (YYYY-MM-DD, YYYY-MM, or YYYY). Defaults to last 24 hours.").option("--page <number>","Page number",parseInt).option("--page-size <number>","Number of results per page (max 1000)",parseInt,100).option("--json","Output result as JSON").action(async s=>{try{let e=await ro(),n={pageSize:s.pageSize};if(s.from&&(n.from=s.from),s.to&&(n.to=s.to),s.trunkId&&(n.trunkId=s.trunkId),s.direction&&(["INBOUND","OUTBOUND"].includes(s.direction.toUpperCase())||(t.error("Invalid direction. Must be INBOUND or OUTBOUND."),process.exit(1)),n.direction=s.direction.toUpperCase()),s.result){let o=["COMPLETED","NO_ANSWER","CANCEL","BUSY","FAILED"];o.includes(s.result.toUpperCase())||(t.error(`Invalid result. Must be one of: ${o.join(", ")}`),process.exit(1)),n.callResult=s.result.toUpperCase()}s.page&&(n.page=s.page),n.createTime=ao(s.date),c.start("Fetching calls...");let i=await e.findCalls(n);c.succeed(`Retrieved ${i.calls?.length||0} call(s)`),s.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.calls&&i.calls.length>0?(i.calls.forEach(o=>{let r=Bt(o.durationSeconds),a=o.callResult||"In Progress",l=_n(o.price);t.info(`${o.callId}`),t.info(` ${o.from} \u2192 ${o.to}`),t.info(` ${o.direction} | ${a} | ${r} | ${l}`),t.info(` ${new Date(o.createTime).toLocaleString()}`),t.newline()}),i.totalItems&&(t.info(`Total: ${i.totalItems} call(s)`),i.pageNumber&&t.info(`Page: ${i.pageNumber}`))):(t.info("No calls found matching the filters"),t.newline(),t.info("Try adjusting your filters or date range.")))}catch(e){c.fail("Failed to fetch calls"),t.error(e.message),process.exit(1)}});Kt.command("get").description("Get details of a specific call").argument("<call-id>","Call ID").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await ro();c.start(`Fetching call ${s}...`);let i=await n.getCall(s);c.succeed("Call retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Wr(i,!0))}catch(n){c.fail("Failed to get call"),t.error(n.message),process.exit(1)}});xt.exports=Kt;xt.exports.parseDateFilter=ao;xt.exports.formatDuration=Bt;xt.exports.formatPrice=_n});var uo=R((dd,po)=>{"use strict";var lo=require("commander"),Gr=Hs(),Yr=Gs(),Zr=Qs(),Qr=to(),Xr=so(),ea=co(),Ne=new lo.Command("sip");Ne.description("Manage Elastic SIP Trunking resources");Ne.addCommand(Gr);Ne.addCommand(Yr);Ne.addCommand(Zr);Ne.addCommand(Qr);Ne.addCommand(Xr);Ne.addCommand(ea);po.exports=Ne});async function re(s){let e={};for(let n of s){if(n.when!==void 0&&!(typeof n.when=="function"?await n.when(e):n.when))continue;let i;switch(n.type){case"input":{let o=await(0,ue.input)({message:n.message,default:n.default,validate:n.validate});n.filter&&(o=n.filter(o)),i=o;break}case"password":i=await(0,ue.password)({message:n.message,validate:n.validate});break;case"confirm":i=await(0,ue.confirm)({message:n.message,default:n.default});break;case"list":i=await(0,ue.select)({message:n.message,choices:(n.choices||[]).map(o=>typeof o=="string"?{name:o,value:o}:o),default:n.default,pageSize:n.pageSize});break;case"checkbox":i=await(0,ue.checkbox)({message:n.message,choices:(n.choices||[]).map(o=>typeof o=="string"?{name:o,value:o}:o),pageSize:n.pageSize});break;default:throw new Error(`Unsupported prompt type: ${n.type}`)}e[n.name]=i}return e}var ue,fo=Q(()=>{"use strict";ue=require("@inquirer/prompts")});var go,Un,qn,mo=Q(()=>{"use strict";go=require("@sinch/sdk-core");k();Un=class{client=null;initialized=!1;async initialize(){if(!(this.initialized&&this.client))try{await u.load();let e=await u.getCredentials();if(!e)throw new Error("Not authenticated. Please run: sinch auth login");this.client=new go.SinchClient({projectId:e.projectId,keyId:e.keyId,keySecret:e.keySecret}),this.initialized=!0}catch(e){throw new Error(`Failed to initialize fax client: ${e.message}`)}}async getClient(){return this.initialized||await this.initialize(),this.client}isInitialized(){return this.initialized}async getServiceConfig(){return await u.load(),{serviceId:u.getFaxServiceId(),senderNumber:u.getFaxSenderNumber()}}async validateConfig(){let e=await this.getServiceConfig(),n=[];return e.serviceId||n.push("fax service ID (set with: sinch config set fax service-id <id>)"),{valid:n.length===0,missing:n}}},qn=new Un});var vo={};ut(vo,{FaxManager:()=>Vt,default:()=>na,getFaxClient:()=>bo,getFaxManager:()=>Ie});async function bo(){try{return await u.load(),await u.hasCredentials()||(t.error("Not authenticated. Please run: sinch auth login"),process.exit(1)),await qn.initialize(),await qn.getClient()}catch(s){t.error(`Failed to initialize fax client: ${s.message}`),process.exit(1)}}async function Ie(){let s=await bo(),e=await u.getFaxCredentials();return new Vt(s,e)}async function ta(){let s=yo.platform();try{if(s==="darwin")return(0,Dt.execSync)(`osascript -e '${`
119
+ `);let n=Cs({project:s.project}).filter(a=>a.installed);if(n.length===0){t.info("No skills installed. Run `sinch skills install` first.");return}let i=ws(),o=W.default.join(i,"sinch-functions"),r=0;for(let a of n)await F.default.copy(o,a.path,{overwrite:!0}),t.success(`Updated ${a.tool} (${a.type})`),r++;t.info(""),t.success(`Updated ${r} skill(s)`)}catch(e){t.error("Failed to update skills:",e.message),process.exit(1)}});bs.exports=st});async function Mr(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1))}async function O(){return await Mr(),await u.createSinchClient()}function ot(s){let e=s||u.get("conversation-app-id");return e||(t.error("No Conversation App ID configured."),t.info("Set default: sinch config set conversation-app-id <id>"),t.info("Or specify: --app <app-id>"),process.exit(1)),e}var We=Q(()=>{"use strict";k();A()});var Ps=R((el,ks)=>{"use strict";var vs=require("commander"),$s=h(require("inquirer"));A();E();We();var Is=new vs.Command("send");Is.description("Send a message via Conversation API").argument("[recipient]","Recipient phone number (e.g., +15551234567)").argument("[message]","Message text to send").option("-c, --channel <channel>","Channel (SMS, WHATSAPP, MESSENGER, etc.)","SMS").option("-a, --app <app-id>","Conversation App ID (uses default if configured)").option("-m, --media <url>","Media URL for media messages").option("--caption <text>","Caption for media messages").option("-t, --template <name>","Template name for template messages").option("-p, --params <json>","Template parameters as JSON string").option("--location","Send location message").option("--lat <latitude>","Latitude for location messages",parseFloat).option("--lng <longitude>","Longitude for location messages",parseFloat).option("-n, --name <name>","Location name").option("--json","Output result as JSON").action(async(s,e,n)=>{try{let i=await O();if(!s||!e&&!n?.media&&!n?.template&&!n?.location){let r=await $s.default.prompt([{type:"input",name:"recipient",message:"Enter recipient phone number:",when:!s,validate:a=>a?a.startsWith("+")?!0:"Phone number must start with +":"Recipient is required"},{type:"input",name:"message",message:"Enter message:",when:!e&&!n?.media&&!n?.template&&!n?.location,validate:a=>a?!0:"Message is required"},{type:"list",name:"channel",message:"Select channel:",choices:["SMS","WHATSAPP","MESSENGER","INSTAGRAM","VIBER","TELEGRAM","RCS","LINE"],default:n?.channel||"SMS",when:!n?.channel}]);s=s||r.recipient,e=e||r.message,r.channel&&(n={...n,channel:r.channel})}let o=ot(n?.app);c.start("Sending message...");try{let r;if(n?.location)(!n.lat||!n.lng)&&(c.fail("Location messages require --lat and --lng"),process.exit(1)),r=await i.conversation.messages.send({sendMessageRequestBody:{app_id:o,recipient:{identified_by:{channel_identities:[{channel:n.channel||"SMS",identity:s}]}},message:{location_message:{coordinates:{latitude:n.lat,longitude:n.lng},title:n.name}}}});else if(n?.template){let a=n.params?JSON.parse(n.params):{};r=await i.conversation.messages.send({sendMessageRequestBody:{app_id:o,recipient:{identified_by:{channel_identities:[{channel:n.channel||"WHATSAPP",identity:s}]}},message:{template_message:{template_reference:{template_id:n.template,version:a.version||"1"},parameters:a}}}})}else n?.media?r=await i.conversation.messages.send({sendMessageRequestBody:{app_id:o,recipient:{identified_by:{channel_identities:[{channel:n.channel||"WHATSAPP",identity:s}]}},message:{media_message:{url:n.media,caption:n.caption}}}}):r=await i.conversation.messages.send({sendMessageRequestBody:{app_id:o,recipient:{identified_by:{channel_identities:[{channel:n?.channel||"SMS",identity:s}]}},message:{text_message:{text:e}}}});c.succeed("Message sent successfully!"),n?.json?console.log(JSON.stringify(r,null,2)):(t.newline(),t.info(`Message ID: ${r.message_id}`),t.info(`Recipient: ${s}`),t.info(`Channel: ${n?.channel||"SMS"}`))}catch(r){c.fail("Failed to send message"),t.error(`Error: ${r.message}`),(r.message?.includes("WHATSAPP")||r.message?.includes("channel not configured"))&&(t.newline(),t.info("To use WhatsApp, configure WhatsApp credentials in your Conversation app:"),t.info(" 1. Visit https://dashboard.sinch.com/convapi/apps"),t.info(" 2. Add WhatsApp channel credentials"),t.info(" 3. Verify your WhatsApp Business Account"),t.newline(),t.info("Or use SMS (no additional setup required):"),t.info(` sinch conversation send ${s} "${e}"`)),process.exit(1)}}catch(i){c.stop(),t.error(`Failed to send message: ${i.message}`),process.exit(1)}});ks.exports=Is});var xs=R((sl,Es)=>{"use strict";var As=require("commander");A();E();We();var It=new As.Command("messages");It.description("Manage conversation messages");It.command("get").description("Get a specific message by ID").argument("<message-id>","Message ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await O();c.start("Fetching message...");let i=await n.conversation.messages.get({message_id:s});c.succeed("Message retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`Message ID: ${i.id}`),t.info(`Direction: ${i.direction}`),t.info(`Channel: ${i.channel_identity?.channel||"N/A"}`),t.info(`Contact ID: ${i.contact_id||"N/A"}`),t.info(`Conversation ID: ${i.conversation_id||"N/A"}`),t.info(`Status: ${i.accept_time?"Accepted":"Pending"}`),i.text_message&&t.info(`Text: ${i.text_message.text}`),i.media_message&&t.info(`Media URL: ${i.media_message.url}`))}catch(n){c.stop(),t.error(`Failed to get message: ${n.message}`),process.exit(1)}});It.command("list").description("List messages").option("-c, --channel <channel>","Filter by channel").option("-l, --limit <number>","Limit number of results",parseInt,20).option("--json","Output result as JSON").action(async s=>{try{let e=await O();c.start("Fetching messages...");let n=await e.conversation.messages.list({page_size:s.limit||20,...s.channel&&{channel:s.channel}});c.succeed(`Retrieved ${n.messages?.length||0} messages`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.messages&&n.messages.length>0?n.messages.forEach(i=>{t.info(`[${i.id}] ${i.direction} via ${i.channel_identity?.channel||"N/A"}`),i.text_message&&t.info(` "${i.text_message.text}"`),t.newline()}):t.info("No messages found"))}catch(e){c.stop(),t.error(`Failed to list messages: ${e.message}`),process.exit(1)}});It.command("delete").description("Delete a message").argument("<message-id>","Message ID to delete").action(async s=>{try{let e=await O();c.start("Deleting message..."),await e.conversation.messages.delete({message_id:s}),c.succeed("Message deleted successfully")}catch(e){c.stop(),t.error(`Failed to delete message: ${e.message}`),process.exit(1)}});Es.exports=It});var Rs=R((cl,js)=>{"use strict";var Ds=require("commander"),Y=h(require("inquirer"));A();E();We();var Ut=class{sinchClient;constructor(e){this.sinchClient=e}hasChannel(e,n){return e.channel_identities?.some(i=>{let o=i.channel;return o==="CHANNEL_UNSPECIFIED"&&i.identity.includes("@")&&(o="EMAIL"),n.includes(o)})}getChannelIdentities(e,n){return e.channel_identities.filter(i=>{let o=i.channel;return o==="CHANNEL_UNSPECIFIED"&&i.identity.includes("@")&&(o="EMAIL"),n.includes(o)})}buildContactMenu(e){let n=this.hasChannel(e,["SMS","WHATSAPP"]),i=this.hasChannel(e,["SMS","WHATSAPP"]),o=this.hasChannel(e,["EMAIL"]),r=[];return n&&r.push({name:"\u{1F4AC} Send Message",value:"send-message"}),r.push({name:"Edit Name",value:"edit-name"}),i&&r.push({name:"Edit Phone",value:"edit-phone"}),o&&r.push({name:"Edit Email",value:"edit-email"}),r.push({name:"Delete Contact",value:"delete"},{name:"See More Details",value:"details"},{name:"\u2190 Back",value:"back"}),r}async sendMessage(e){let n=e.channel_identities.map(r=>{let a=r.channel;return a==="CHANNEL_UNSPECIFIED"&&r.identity.includes("@")&&(a="EMAIL"),{name:`${a}: ${r.identity}`,value:{channel:a,identity:r.identity}}});n.push({name:"\u2190 Back",value:"back"});let{selectedChannel:i}=await Y.default.prompt([{type:"list",name:"selectedChannel",message:"Select channel to send to:",choices:n}]);if(i==="back")return!1;let{messageText:o}=await Y.default.prompt([{type:"input",name:"messageText",message:"Enter your message:",validate:r=>r?!0:"Message is required"}]);try{let r=ot();c.start("Sending message...");let a=await this.sinchClient.conversation.messages.send({sendMessageRequestBody:{app_id:r,recipient:{identified_by:{channel_identities:[{channel:i.channel,identity:i.identity,app_id:""}]}},message:{text_message:{text:o}}}});c.succeed("Message sent successfully!"),t.newline(),t.info(`Message ID: ${a.message_id}`),t.info(`Recipient: ${i.identity}`),t.info(`Channel: ${i.channel}`),t.newline()}catch(r){c.fail("Failed to send message"),t.error(`Error: ${r.message}`),t.newline()}return!1}showDetails(e){t.newline(),t.info("Contact Details:"),t.info(`ID: ${e.id}`),t.info(`Display Name: ${e.display_name||"N/A"}`),t.info(`Email: ${e.email||"N/A"}`),t.info(`External ID: ${e.external_id||"N/A"}`),t.info(`Language: ${e.language||"N/A"}`),t.info(`Metadata: ${e.metadata||"N/A"}`),e.channel_identities&&e.channel_identities.length>0&&(t.newline(),t.info("Channel Identities:"),e.channel_identities.forEach(n=>{let i=n.channel;i==="CHANNEL_UNSPECIFIED"&&n.identity.includes("@")&&(i="EMAIL"),t.info(` ${i}: ${n.identity}`)})),t.newline()}async editName(e,n){let{newDisplayName:i}=await Y.default.prompt([{type:"input",name:"newDisplayName",message:"Enter new display name:",default:e.display_name}]);c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:n,display_name:i}),c.succeed("Contact updated successfully!"),e.display_name=i,t.newline()}async editChannelIdentities(e,n,i){let r={phone:{channels:["SMS","WHATSAPP"],addPrompt:"+ Add new phone number",selectPrompt:"Select phone number to edit or add new:",typePrompt:"Select type:",valuePrompt:"Enter phone number:",editPrompt:"Enter new phone number:",typeChoices:["SMS","WHATSAPP"],successAdd:"Phone number added successfully!",successEdit:"Phone number updated successfully!",successDelete:"Phone number deleted successfully!",validator:d=>d?d.startsWith("+")?!0:"Phone number must start with +":"Phone number is required"},email:{channels:["EMAIL"],addPrompt:"+ Add new email address",selectPrompt:"Select email address to edit or add new:",typePrompt:null,valuePrompt:"Enter email address:",editPrompt:"Enter new email address:",typeChoices:null,successAdd:"Email address added successfully!",successEdit:"Email address updated successfully!",successDelete:"Email address deleted successfully!",validator:d=>d?d.includes("@")?!0:"Invalid email address":"Email is required"}}[i],l=this.getChannelIdentities(e,r.channels).map(d=>{let f=e.channel_identities.indexOf(d),g=d.channel;return g==="CHANNEL_UNSPECIFIED"&&d.identity.includes("@")&&(g="EMAIL"),{name:`${g}: ${d.identity}`,value:f}});l.push({name:r.addPrompt,value:"add"}),l.push({name:"\u2190 Back",value:"cancel"});let{identityAction:p}=await Y.default.prompt([{type:"list",name:"identityAction",message:r.selectPrompt,choices:l}]);if(p!=="cancel")if(p==="add"){let d=[];r.typePrompt&&r.typeChoices&&d.push({type:"list",name:"newIdentityType",message:r.typePrompt,choices:r.typeChoices}),d.push({type:"input",name:"newIdentityValue",message:r.valuePrompt,validate:r.validator});let f=await Y.default.prompt(d);e.channel_identities.push({channel:f.newIdentityType||r.channels[0],identity:f.newIdentityValue,app_id:""}),c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:n,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(r.successAdd),t.newline()}else{let d=e.channel_identities[p],{editOrDelete:f}=await Y.default.prompt([{type:"list",name:"editOrDelete",message:"What would you like to do?",choices:["Edit","Delete","\u2190 Back"]}]);if(f==="Edit"){let{newValue:g}=await Y.default.prompt([{type:"input",name:"newValue",message:r.editPrompt,default:d.identity,validate:r.validator}]);d.identity=g,c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:n,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(r.successEdit),t.newline()}else f==="Delete"&&(e.channel_identities.splice(p,1),c.start("Updating contact..."),await this.sinchClient.conversation.contact.update({contact_id:n,channel_identities:e.channel_identities,display_name:e.display_name}),c.succeed(r.successDelete),t.newline())}}async deleteContact(e,n,i){let{confirmDelete:o}=await Y.default.prompt([{type:"confirm",name:"confirmDelete",message:`Are you sure you want to delete "${e.display_name||"this contact"}"?`,default:!1}]);if(o){c.start("Deleting contact..."),await this.sinchClient.conversation.contact.delete({contact_id:n}),c.succeed("Contact deleted successfully");let r=i.findIndex(a=>a.id===n);if(r>-1&&i.splice(r,1),i.length===0)return t.info("No more contacts."),!0;t.newline()}return!1}async handleAction(e,n,i,o){switch(e){case"send-message":return await this.sendMessage(n);case"details":return this.showDetails(n),!1;case"edit-name":return await this.editName(n,i),!1;case"edit-phone":return await this.editChannelIdentities(n,i,"phone"),!1;case"edit-email":return await this.editChannelIdentities(n,i,"email"),!1;case"delete":return await this.deleteContact(n,i,o);default:return!1}}async runInteractiveList(e){let n=!0;for(;n;){let i=[];e.forEach(p=>{i.push(new Y.default.Separator(`
120
+ ${p.display_name||"No name"}`)),p.channel_identities&&p.channel_identities.length>0&&p.channel_identities.forEach(d=>{let f=d.channel;f==="CHANNEL_UNSPECIFIED"&&d.identity.includes("@")&&(f="EMAIL"),i.push(new Y.default.Separator(`${f}: ${d.identity}`))}),i.push({name:"Edit Delete More",value:`menu:${p.id}`})}),i.push(new Y.default.Separator("")),i.push({name:"\u2190 Exit",value:"exit"});let{action:o}=await Y.default.prompt([{type:"list",name:"action",message:"Contacts",choices:i,pageSize:20}]);if(o==="exit")break;if(!o||!o.includes(":"))continue;let[r,a]=o.split(":"),l=e.find(p=>p.id===a);if(r==="menu"){let p=this.buildContactMenu(l),{subAction:d}=await Y.default.prompt([{type:"list",name:"subAction",message:`Actions for ${l.display_name||"contact"}:`,choices:p}]);if(d==="back")continue;await this.handleAction(d,l,a,e)&&(n=!1)}}}},je=new Ds.Command("contacts");je.description("Manage conversation contacts");je.command("create").description("Create a new contact").option("-p, --phone <number>","Phone number").option("-e, --email <email>","Email address").option("-n, --name <name>","Contact name").option("-d, --display-name <name>","Display name").option("--json","Output result as JSON").action(async s=>{try{if(!s.phone&&!s.email){let r=await Y.default.prompt([{type:"input",name:"phone",message:"Enter phone number (optional):",validate:a=>a&&!a.startsWith("+")?"Phone number must start with +":!0},{type:"input",name:"email",message:"Enter email address (optional):"},{type:"input",name:"name",message:"Enter contact name (optional):"}]);s={...s,...r}}!s.phone&&!s.email&&(t.error("At least one of phone or email is required"),process.exit(1));let e=await O();c.start("Creating contact...");let n=[];s.phone&&n.push({channel:"SMS",identity:s.phone}),s.email&&n.push({channel:"EMAIL",identity:s.email});let i={contactCreateRequestBody:{channel_identities:n,display_name:s.displayName||s.name,language:"EN_US"}},o=await e.conversation.contact.create(i);c.succeed("Contact created successfully!"),s.json||(t.newline(),t.info(`Contact ID: ${o.id}`),t.info(`Display Name: ${o.display_name||"N/A"}`),s.phone&&t.info(`Phone: ${s.phone}`),s.email&&t.info(`Email: ${s.email}`))}catch(e){c.stop(),t.error(`Failed to create contact: ${e.message}`),e.response?.data&&t.error("API Response:",JSON.stringify(e.response.data,null,2)),e.data&&t.error("Error data:",JSON.stringify(e.data,null,2)),process.exit(1)}});je.command("get").description("Get a specific contact by ID").argument("<contact-id>","Contact ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await O();c.start("Fetching contact...");let i=await n.conversation.contact.get({contact_id:s});c.succeed("Contact retrieved"),e.json?console.log(JSON.stringify(i,null,2)):new Ut(n).showDetails(i)}catch(n){c.stop(),t.error(`Failed to get contact: ${n.message}`),process.exit(1)}});je.command("list").description("List contacts").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").option("--no-interactive","Disable interactive mode").action(async s=>{try{let e=await O();c.start("Fetching contacts...");let n=await e.conversation.contact.list({page_size:s.limit||50}),i=n.data||n.contacts||[];if(c.succeed(`Retrieved ${i.length} contacts`),s.json){console.log(JSON.stringify(n,null,2));return}i&&i.length>0?(t.newline(),t.newline(),s.interactive!==!1?await new Ut(e).runInteractiveList(i):i.forEach(o=>{t.info(o.display_name||"No name"),o.channel_identities&&o.channel_identities.length>0&&o.channel_identities.forEach(r=>{let a=r.channel;a==="CHANNEL_UNSPECIFIED"&&r.identity.includes("@")&&(a="EMAIL"),t.info(`${a}: ${r.identity}`)}),t.newline()})):(t.newline(),t.info("No contacts found"))}catch(e){c.stop(),t.error(`Failed to list contacts: ${e.message}`),process.exit(1)}});je.command("update").description("Update a contact").argument("<contact-id>","Contact ID to update").option("-n, --name <name>","New contact name").option("-d, --display-name <name>","New display name").option("--json","Output result as JSON").action(async(s,e)=>{try{!e.displayName&&!e.name&&(t.error("At least one update field is required (--name or --display-name)"),process.exit(1));let n=await O();c.start("Updating contact...");let i=await n.conversation.contact.update({contact_id:s,display_name:e.displayName||e.name,...e.name&&{metadata:JSON.stringify({name:e.name})}});c.succeed("Contact updated successfully!"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`Contact ID: ${i.id}`),t.info(`Display Name: ${i.display_name||"N/A"}`))}catch(n){c.stop(),t.error(`Failed to update contact: ${n.message}`),process.exit(1)}});je.command("delete").description("Delete a contact").argument("<contact-id>","Contact ID to delete").action(async s=>{try{let e=await O();c.start("Deleting contact..."),await e.conversation.contact.delete({contact_id:s}),c.succeed("Contact deleted successfully")}catch(e){c.stop(),t.error(`Failed to delete contact: ${e.message}`),process.exit(1)}});je.command("merge").description("Merge two contacts").argument("<source-id>","Source contact ID (will be merged into destination)").argument("<dest-id>","Destination contact ID").option("--json","Output result as JSON").action(async(s,e,n)=>{try{let i=await O();c.start("Merging contacts...");let o=await i.conversation.contact.mergeContact({destination_id:e,source_id:s});c.succeed("Contacts merged successfully!"),n.json?console.log(JSON.stringify(o,null,2)):(t.newline(),t.info(`Source contact ${s} merged into ${e}`),t.info(`Result Contact ID: ${o.id}`))}catch(i){c.stop(),t.error(`Failed to merge contacts: ${i.message}`),process.exit(1)}});js.exports=je});var Ts=R((ul,Os)=>{"use strict";var Ns=require("commander");A();E();We();var kt=new Ns.Command("conversations");kt.description("Manage conversations");kt.command("list").description("List conversations").option("-a, --app <app-id>","Filter by Conversation App ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async s=>{try{let e=await O();c.start("Fetching conversations...");let n=await e.conversation.conversation.list({page_size:s.limit||50,...s.app&&{app_id:s.app}});c.succeed(`Retrieved ${n.conversations?.length||0} conversations`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.conversations&&n.conversations.length>0?n.conversations.forEach(i=>{t.info(`[${i.id}]`),t.info(` App ID: ${i.app_id}`),t.info(` Active: ${i.active_channel||"N/A"}`),t.info(` Last Updated: ${i.last_received?new Date(i.last_received).toLocaleString():"N/A"}`),t.newline()}):t.info("No conversations found"))}catch(e){c.stop(),t.error(`Failed to list conversations: ${e.message}`),process.exit(1)}});kt.command("get").description("Get a specific conversation by ID").argument("<conversation-id>","Conversation ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await O();c.start("Fetching conversation...");let i=await n.conversation.conversation.get({conversation_id:s});c.succeed("Conversation retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`Conversation ID: ${i.id}`),t.info(`App ID: ${i.app_id}`),t.info(`Active Channel: ${i.active_channel||"N/A"}`),t.info(`Contact ID: ${i.contact_id||"N/A"}`),i.metadata&&(t.newline(),t.info("Metadata:"),t.info(JSON.stringify(i.metadata,null,2))))}catch(n){c.stop(),t.error(`Failed to get conversation: ${n.message}`),process.exit(1)}});kt.command("stop").description("Stop an active conversation").argument("<conversation-id>","Conversation ID to stop").action(async s=>{try{let e=await O();c.start("Stopping conversation..."),await e.conversation.conversation.delete({conversation_id:s}),c.succeed("Conversation stopped successfully")}catch(e){c.stop(),t.error(`Failed to stop conversation: ${e.message}`),process.exit(1)}});Os.exports=kt});var _s=R((hl,Ls)=>{"use strict";var Fs=require("commander"),An=h(require("inquirer"));A();E();We();var rt=new Fs.Command("apps");rt.description("Manage Conversation apps");rt.command("list").description("List Conversation apps").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async s=>{try{let e=await O();c.start("Fetching apps...");let n=await e.conversation.app.list({page_size:s.limit||50});c.succeed(`Retrieved ${n.apps?.length||0} apps`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.apps&&n.apps.length>0?n.apps.forEach(i=>{t.info(`[${i.id}] ${i.display_name||"No name"}`),t.info(` Channels: ${i.channel_credentials?.length||0} configured`),t.newline()}):t.info("No apps found"))}catch(e){c.stop(),t.error(`Failed to list apps: ${e.message}`),process.exit(1)}});rt.command("get").description("Get a specific Conversation app by ID").argument("<app-id>","App ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await O();c.start("Fetching app...");let i=await n.conversation.app.get({app_id:s});c.succeed("App retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`App ID: ${i.id}`),t.info(`Display Name: ${i.display_name||"N/A"}`),t.info("Rate Limits:",i.rate_limits||"N/A"),i.channel_credentials&&i.channel_credentials.length>0&&(t.newline(),t.info("Configured Channels:"),i.channel_credentials.forEach(o=>{t.info(` - ${o.channel}`)})),i.conversation_metadata_report_view&&(t.newline(),t.info(`Metadata Report: ${i.conversation_metadata_report_view}`)))}catch(n){c.stop(),t.error(`Failed to get app: ${n.message}`),process.exit(1)}});rt.command("create").description("Create a new Conversation app").argument("[name]","App display name").option("--json","Output result as JSON").action(async(s,e)=>{try{s||(s=(await An.default.prompt([{type:"input",name:"name",message:"Enter app display name:",validate:r=>r?!0:"App name is required"}])).name);let n=await O();c.start("Creating app...");let i=await n.conversation.app.create({display_name:s});c.succeed("App created successfully!"),e?.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`App ID: ${i.id}`),t.info(`Display Name: ${i.display_name}`),t.newline(),t.info("\u{1F4A1} Set as default: sinch config set conversation-app-id "+i.id))}catch(n){c.stop(),t.error(`Failed to create app: ${n.message}`),process.exit(1)}});rt.command("delete").description("Delete a Conversation app").argument("<app-id>","App ID to delete").action(async s=>{try{let{confirm:e}=await An.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete app ${s}?`,default:!1}]);if(!e){t.info("Deletion cancelled");return}let n=await O();c.start("Deleting app..."),await n.conversation.app.delete({app_id:s}),c.succeed("App deleted successfully")}catch(e){c.stop(),t.error(`Failed to delete app: ${e.message}`),process.exit(1)}});Ls.exports=rt});var Ms=R((Sl,qs)=>{"use strict";var Us=require("commander"),En=h(require("inquirer"));k();A();E();We();var at=new Us.Command("webhooks");at.description("Manage webhooks for Conversation apps");at.command("list").description("List webhooks for a Conversation app").option("-a, --app <app-id>","Conversation App ID").option("--json","Output result as JSON").action(async s=>{try{let e=ot(s.app),n=await O();c.start("Fetching webhooks...");let i=await n.conversation.webhooks.list({app_id:e});c.succeed(`Retrieved ${i.webhooks?.length||0} webhooks`),s.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.webhooks&&i.webhooks.length>0?i.webhooks.forEach(o=>{t.info(`[${o.id}]`),t.info(` URL: ${o.target}`),t.info(` Triggers: ${o.triggers?.join(", ")||"N/A"}`),t.info(` Secret: ${o.secret?"********":"Not set"}`),t.newline()}):t.info("No webhooks found for this app"))}catch(e){c.stop(),t.error(`Failed to list webhooks: ${e.message}`),process.exit(1)}});at.command("create").description("Create a new webhook for a Conversation app").option("-a, --app <app-id>","Conversation App ID").option("-u, --url <url>","Webhook URL").option("-t, --triggers <triggers>","Comma-separated list of triggers (e.g., MESSAGE_INBOUND,MESSAGE_DELIVERY)").option("-s, --secret <secret>","Webhook secret for signature validation").option("--json","Output result as JSON").action(async s=>{try{await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=s.app;if(!n){let a=u.get("conversation-app-id");a&&(n=a,t.info(`Using default app: ${n}`))}if(!n||!s.url||!s.triggers){let a=await En.default.prompt([{type:"input",name:"appId",message:"Enter Conversation App ID:",when:!n,validate:l=>l?!0:"App ID is required"},{type:"input",name:"url",message:"Enter webhook URL:",when:!s.url,validate:l=>{if(!l)return"URL is required";try{return new URL(l),!0}catch{return"Please enter a valid URL"}}},{type:"checkbox",name:"triggers",message:"Select webhook triggers:",when:!s.triggers,choices:["MESSAGE_INBOUND","MESSAGE_DELIVERY","MESSAGE_SUBMIT","EVENT_INBOUND","CONVERSATION_START","CONVERSATION_STOP","CONTACT_CREATE","CONTACT_DELETE","CONTACT_MERGE","CONTACT_UPDATE"],validate:l=>l.length>0?!0:"Select at least one trigger"},{type:"input",name:"secret",message:"Enter webhook secret (optional, press enter to skip):"}]);n=n||a.appId,s.url=s.url||a.url,s.triggers=s.triggers||a.triggers.join(","),s.secret=s.secret||a.secret}let i=await O(),o=s.triggers.split(",").map(a=>a.trim());c.start("Creating webhook...");let r=await i.conversation.webhooks.create({app_id:n,target:s.url,triggers:o,...s.secret&&{secret:s.secret}});c.succeed("Webhook created successfully!"),s.json?console.log(JSON.stringify(r,null,2)):(t.newline(),t.info(`Webhook ID: ${r.id}`),t.info(`URL: ${r.target}`),t.info(`Triggers: ${r.triggers?.join(", ")}`),s.secret&&t.info("Secret: ********"))}catch(e){c.stop(),t.error(`Failed to create webhook: ${e.message}`),process.exit(1)}});at.command("update").description("Update a webhook").argument("<webhook-id>","Webhook ID to update").option("-u, --url <url>","New webhook URL").option("-t, --triggers <triggers>","New comma-separated list of triggers").option("-s, --secret <secret>","New webhook secret").option("--json","Output result as JSON").action(async(s,e)=>{try{!e.url&&!e.triggers&&!e.secret&&(t.error("At least one update field is required (--url, --triggers, or --secret)"),process.exit(1));let n=await O(),i={};e.url&&(i.target=e.url),e.triggers&&(i.triggers=e.triggers.split(",").map(r=>r.trim())),e.secret&&(i.secret=e.secret),c.start("Updating webhook...");let o=await n.conversation.webhooks.update({webhook_id:s,...i});c.succeed("Webhook updated successfully!"),e.json?console.log(JSON.stringify(o,null,2)):(t.newline(),t.info(`Webhook ID: ${o.id}`),t.info(`URL: ${o.target}`),t.info(`Triggers: ${o.triggers?.join(", ")}`))}catch(n){c.stop(),t.error(`Failed to update webhook: ${n.message}`),process.exit(1)}});at.command("delete").description("Delete a webhook").argument("<webhook-id>","Webhook ID to delete").action(async s=>{try{let{confirm:e}=await En.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete webhook ${s}?`,default:!1}]);if(!e){t.info("Deletion cancelled");return}let n=await O();c.start("Deleting webhook..."),await n.conversation.webhooks.delete({webhook_id:s}),c.succeed("Webhook deleted successfully")}catch(e){c.stop(),t.error(`Failed to delete webhook: ${e.message}`),process.exit(1)}});qs.exports=at});var Ks=R((vl,Bs)=>{"use strict";var Js=require("commander"),Jr=Ps(),Br=xs(),Kr=Rs(),Vr=Ts(),Hr=_s(),zr=Ms(),Re=new Js.Command("conversation");Re.description("Manage Sinch Conversations API");Re.addCommand(Jr);Re.addCommand(Br);Re.addCommand(Kr);Re.addCommand(Vr);Re.addCommand(Hr);Re.addCommand(zr);Bs.exports=Re});var xn,Pt,te,Ge=Q(()=>{"use strict";xn=h(require("axios")),Pt=h(require("chalk")),te=class{baseUrl="https://elastic-trunking.api.sinch.com";projectId;credentials;client;timeout=6e4;constructor(e){this.projectId=e.projectId,this.credentials=e.credentials,this.client=xn.default.create({baseURL:this.baseUrl,timeout:this.timeout,headers:{"Content-Type":"application/json","User-Agent":"sinch-functions-cli/1.0.0"}}),this.client.interceptors.request.use(async n=>{let i=await this.getAuthHeader();return i&&(n.headers.Authorization=i),process.env.DEBUG_HTTP&&console.log(Pt.default.gray(`\u2192 ${n.method?.toUpperCase()} ${n.url}`)),n},n=>Promise.reject(n)),this.client.interceptors.response.use(n=>(process.env.DEBUG_HTTP&&console.log(Pt.default.gray(`\u2190 ${n.status} ${n.config.url}`)),n),n=>(process.env.DEBUG_HTTP&&console.log(Pt.default.red(`\u2190 ${n.response?.status||"ERROR"} ${n.config?.url}`)),Promise.reject(n)))}async getAuthHeader(){try{let e=await this.credentials.retrieve();return e&&e.keyId&&e.keySecret?`Basic ${Buffer.from(`${e.keyId}:${e.keySecret}`).toString("base64")}`:null}catch{return console.error(Pt.default.yellow("Failed to get authentication credentials")),null}}async listTrunks(e={}){try{let n={};return e.page&&(n.pageToken=e.page),e.pageSize&&(n.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks`,{params:n})).data}catch(n){throw this.handleError(n,"Failed to list SIP trunks")}}async getTrunk(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}`)).data}catch(n){throw this.handleError(n,`Failed to get SIP trunk ${e}`)}}async createTrunk(e){try{return(await this.client.post(`/v1/projects/${this.projectId}/trunks`,e)).data}catch(n){throw this.handleError(n,"Failed to create SIP trunk")}}async updateTrunk(e,n){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}`,n)).data}catch(i){throw this.handleError(i,`Failed to update SIP trunk ${e}`)}}async deleteTrunk(e){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}`)}catch(n){throw this.handleError(n,`Failed to delete SIP trunk ${e}`)}}async listEndpoints(e,n={}){try{let i={};return n.page&&(i.pageToken=n.page),n.pageSize&&(i.pageSize=n.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/endpoints`,{params:i})).data}catch(i){throw this.handleError(i,`Failed to list endpoints for trunk ${e}`)}}async getEndpoint(e,n){try{return(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${n}`)).data}catch(i){throw this.handleError(i,`Failed to get endpoint ${n}`)}}async createEndpoint(e,n){try{return(await this.client.post(`/v1/projects/${this.projectId}/trunks/${e}/endpoints`,n)).data}catch(i){throw this.handleError(i,"Failed to create SIP endpoint")}}async updateEndpoint(e,n,i){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${n}`,i)).data}catch(o){throw this.handleError(o,`Failed to update endpoint ${n}`)}}async deleteEndpoint(e,n){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}/endpoints/${n}`)}catch(i){throw this.handleError(i,`Failed to delete endpoint ${n}`)}}async listAcls(e={}){try{let n={};return e.page&&(n.pageToken=e.page),e.pageSize&&(n.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists`,{params:n})).data}catch(n){throw this.handleError(n,"Failed to list ACLs")}}async getAcl(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}`)).data}catch(n){throw this.handleError(n,`Failed to get ACL ${e}`)}}async createAcl(e){try{return(await this.client.post(`/v1/projects/${this.projectId}/accessControlLists`,e)).data}catch(n){throw this.handleError(n,"Failed to create ACL")}}async updateAcl(e,n){try{return(await this.client.put(`/v1/projects/${this.projectId}/accessControlLists/${e}`,n)).data}catch(i){throw this.handleError(i,`Failed to update ACL ${e}`)}}async deleteAcl(e){try{await this.client.delete(`/v1/projects/${this.projectId}/accessControlLists/${e}`)}catch(n){throw this.handleError(n,`Failed to delete ACL ${e}`)}}async getAclTrunks(e,n={}){try{let i={};return n.page&&(i.pageToken=n.page),n.pageSize&&(i.pageSize=n.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/trunks`,{params:i})).data}catch(i){throw this.handleError(i,`Failed to get trunks for ACL ${e}`)}}async listIpRanges(e,n={}){try{let i={};return n.page&&(i.pageToken=n.page),n.pageSize&&(i.pageSize=n.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges`,{params:i})).data}catch(i){throw this.handleError(i,`Failed to list IP ranges for ACL ${e}`)}}async getIpRange(e,n){try{return(await this.client.get(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${n}`)).data}catch(i){throw this.handleError(i,`Failed to get IP range ${n}`)}}async addIpRange(e,n){try{return(await this.client.post(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges`,n)).data}catch(i){throw this.handleError(i,`Failed to add IP range to ACL ${e}`)}}async updateIpRange(e,n,i){try{return(await this.client.put(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${n}`,i)).data}catch(o){throw this.handleError(o,`Failed to update IP range ${n}`)}}async deleteIpRange(e,n){try{await this.client.delete(`/v1/projects/${this.projectId}/accessControlLists/${e}/ipRanges/${n}`)}catch(i){throw this.handleError(i,`Failed to delete IP range ${n}`)}}async listCountryPermissions(e={}){try{let n={};return e.page&&(n.pageToken=e.page),e.pageSize&&(n.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/countryPermissions`,{params:n})).data}catch(n){throw this.handleError(n,"Failed to list country permissions")}}async getCountryPermission(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/countryPermissions/${e}`)).data}catch(n){throw this.handleError(n,`Failed to get country permission for ${e}`)}}async updateCountryPermission(e,n){try{return(await this.client.put(`/v1/projects/${this.projectId}/countryPermissions/${e}`,{enabled:n})).data}catch(i){throw this.handleError(i,`Failed to update country permission for ${e}`)}}async listTrunkAcls(e,n={}){try{let i={};return n.page&&(i.pageToken=n.page),n.pageSize&&(i.pageSize=n.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists`,{params:i})).data}catch(i){throw this.handleError(i,`Failed to list ACLs for trunk ${e}`)}}async addTrunkAcl(e,n){try{await this.client.post(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists`,{accessControlListId:n})}catch(i){throw this.handleError(i,`Failed to add ACL ${n} to trunk ${e}`)}}async removeTrunkAcl(e,n){try{await this.client.delete(`/v1/projects/${this.projectId}/trunks/${e}/accessControlLists/${n}`)}catch(i){throw this.handleError(i,`Failed to remove ACL ${n} from trunk ${e}`)}}async getCredentialListTrunks(e,n={}){try{let i={};return n.page&&(i.pageNumber=n.page),n.pageSize&&(i.pageSize=n.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/credentialLists/${e}/trunks`,{params:i})).data}catch(i){throw this.handleError(i,`Failed to get trunks for credential list ${e}`)}}async updateTrunkCredentialLists(e,n){try{return(await this.client.put(`/v1/projects/${this.projectId}/trunks/${e}/credentialLists`,{credentialListIds:n})).data}catch(i){throw this.handleError(i,`Failed to update credential lists for trunk ${e}`)}}async findCalls(e={}){try{let n={};return e.from&&(n.from=e.from),e.to&&(n.to=e.to),e.trunkId&&(n.trunkId=e.trunkId),e.createTime&&(n.createTime=e.createTime),e.callResult&&(n.callResult=e.callResult),e.direction&&(n.direction=e.direction),e.page&&(n.pageNumber=e.page),e.pageSize&&(n.pageSize=e.pageSize),(await this.client.get(`/v1/projects/${this.projectId}/calls`,{params:n})).data}catch(n){throw this.handleError(n,"Failed to find calls")}}async getCall(e){try{return(await this.client.get(`/v1/projects/${this.projectId}/calls/${e}`)).data}catch(n){throw this.handleError(n,`Failed to get call ${e}`)}}handleError(e,n){if(xn.default.isAxiosError(e)){let i=e;if(i.response){let o=i.response.status,r=i.response.data,a=r?.message||r?.error||i.message;throw o===401?new Error('Authentication required. Please run "sinch auth login" first.'):o===403?new Error(`Permission denied: ${a}`):o===404?new Error(`Resource not found: ${a}`):o>=500?new Error(`Server error: ${a}`):new Error(`${n}: ${a}`)}else throw i.request?i.code==="ECONNREFUSED"?new Error(`Cannot connect to EST API at ${this.baseUrl}`):i.code==="ETIMEDOUT"?new Error(`Request timeout after ${this.timeout}ms`):new Error(`${n}: No response from server (${i.code||"unknown error"})`):new Error(`${n}: ${i.message}`)}else throw new Error(`${n}: ${e.message||e}`)}}});var Hs=R((jl,Vs)=>{"use strict";var qt=require("commander"),be=h(require("inquirer"));A();E();k();Ge();async function Se(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}function Dn(s){t.info(`ID: ${s.id}`),t.info(`Name: ${s.name}`),s.hostName&&t.info(`Host: ${s.hostName}`),t.info(`Caller ID: ${s.enableCallerId?"enabled":"disabled"}`),s.createTime&&t.info(`Created: ${new Date(s.createTime).toLocaleString()}`),s.updateTime&&t.info(`Updated: ${new Date(s.updateTime).toLocaleString()}`)}var ve=new qt.Command("trunks");ve.description("Manage SIP trunks");ve.command("list").description("List all SIP trunks").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async s=>{try{let e=await Se();c.start("Fetching SIP trunks...");let n=await e.listTrunks({pageSize:s.limit});c.succeed(`Retrieved ${n.trunks?.length||0} trunk(s)`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.trunks&&n.trunks.length>0?n.trunks.forEach(i=>{t.info(`[${i.id}] ${i.name}`),i.hostName&&t.info(` Host: ${i.hostName}`),t.info(` Caller ID: ${i.enableCallerId?"enabled":"disabled"}`),t.newline()}):(t.info("No SIP trunks found"),t.newline(),t.info("Create one with: sinch sip trunks create")))}catch(e){c.stop(),t.error(`Failed to list trunks: ${e.message}`),process.exit(1)}});ve.command("get").description("Get a SIP trunk by ID").argument("<trunk-id>","Trunk ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Se();c.start("Fetching trunk...");let i=await n.getTrunk(s);c.succeed("Trunk retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Dn(i))}catch(n){c.stop(),t.error(`Failed to get trunk: ${n.message}`),process.exit(1)}});ve.command("create").description("Create a new SIP trunk").option("-n, --name <name>","Trunk name (required)").option("-h, --host-name <hostname>","Host name for the trunk (required)").option("--caller-id","Enable caller ID").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async s=>{try{let e=s.name,n=s.hostName,i=s.callerId??!1,o=!s.nonInteractive;e||(o?e=(await be.default.prompt([{type:"input",name:"name",message:"Enter trunk name:",validate:p=>p?!0:"Trunk name is required"}])).name:(t.error("Name is required. Use --name <name>"),process.exit(1))),n||(o?n=(await be.default.prompt([{type:"input",name:"hostName",message:"Enter host name:",validate:p=>p?!0:"Host name is required"}])).hostName:(t.error("Host name is required. Use --host-name <hostname>"),process.exit(1))),s.callerId===void 0&&o&&(i=(await be.default.prompt([{type:"confirm",name:"enableCallerId",message:"Enable caller ID?",default:!1}])).enableCallerId);let r=await Se();c.start("Creating SIP trunk...");let a=await r.createTrunk({name:e,hostName:n,enableCallerId:i});c.succeed("SIP trunk created successfully!"),s.json?console.log(JSON.stringify(a,null,2)):(t.newline(),Dn(a),t.newline(),t.info(`Add an endpoint: sinch sip endpoints create ${a.id}`))}catch(e){c.stop(),t.error(`Failed to create trunk: ${e.message}`),process.exit(1)}});ve.command("update").description("Update a SIP trunk").argument("<trunk-id>","Trunk ID to update").option("-n, --name <name>","New trunk name").option("-h, --host-name <hostname>","New host name").option("--caller-id","Enable caller ID").option("--no-caller-id","Disable caller ID").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Se();c.start("Fetching current trunk details...");let i=await n.getTrunk(s);c.stop();let o=e.name,r=e.hostName,a=e.callerId,l=!e.nonInteractive;o||(l?o=(await be.default.prompt([{type:"input",name:"name",message:"Enter trunk name:",default:i.name,validate:f=>f?!0:"Trunk name is required"}])).name:o=i.name),r===void 0&&(l?r=(await be.default.prompt([{type:"input",name:"hostName",message:"Enter host name:",default:i.hostName||""}])).hostName||void 0:r=i.hostName),a===void 0&&(l?a=(await be.default.prompt([{type:"confirm",name:"enableCallerId",message:"Enable caller ID?",default:i.enableCallerId??!1}])).enableCallerId:a=i.enableCallerId),c.start("Updating SIP trunk...");let p=await n.updateTrunk(s,{name:o,hostName:r,enableCallerId:a});c.succeed("SIP trunk updated successfully!"),e.json?console.log(JSON.stringify(p,null,2)):(t.newline(),Dn(p))}catch(n){c.stop(),t.error(`Failed to update trunk: ${n.message}`),process.exit(1)}});ve.command("delete").description("Delete a SIP trunk").argument("<trunk-id>","Trunk ID to delete").option("-f, --force","Skip confirmation prompt").action(async(s,e)=>{try{if(!e.force){let{confirm:i}=await be.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete trunk ${s}?`,default:!1}]);if(!i){t.info("Deletion cancelled");return}}let n=await Se();c.start("Deleting SIP trunk..."),await n.deleteTrunk(s),c.succeed("SIP trunk deleted successfully")}catch(n){c.stop(),t.error(`Failed to delete trunk: ${n.message}`),process.exit(1)}});var At=new qt.Command("acls");At.description("Manage ACLs for a trunk");At.command("list").description("List ACLs associated with a trunk").argument("<trunk-id>","Trunk ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Se();c.start("Fetching trunk ACLs...");let i=await n.listTrunkAcls(s,{pageSize:e.limit});c.succeed(`Retrieved ${i.accessControlLists?.length||0} ACL(s)`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.accessControlLists&&i.accessControlLists.length>0?i.accessControlLists.forEach(o=>{let r=o.enabled!==!1?"":" (disabled)";t.info(`[${o.id}] ${o.name}${r}`),t.newline()}):(t.info("No ACLs associated with this trunk"),t.newline(),t.info(`Add an ACL: sinch sip trunks acls add ${s} <acl-id>`)))}catch(n){c.stop(),t.error(`Failed to list trunk ACLs: ${n.message}`),process.exit(1)}});At.command("add").description("Add an ACL to a trunk").argument("<trunk-id>","Trunk ID").argument("<acl-id>","ACL ID to add").option("--json","Output result as JSON").action(async(s,e,n)=>{try{let i=await Se();c.start(`Adding ACL ${e} to trunk ${s}...`),await i.addTrunkAcl(s,e),c.succeed("ACL added to trunk successfully"),n.json||(t.newline(),t.info(`ACL ${e} is now associated with trunk ${s}`))}catch(i){c.stop(),t.error(`Failed to add ACL to trunk: ${i.message}`),process.exit(1)}});At.command("remove").description("Remove an ACL from a trunk").argument("<trunk-id>","Trunk ID").argument("<acl-id>","ACL ID to remove").option("-f, --force","Skip confirmation prompt").action(async(s,e,n)=>{try{if(!n.force){let{confirm:o}=await be.default.prompt([{type:"confirm",name:"confirm",message:`Remove ACL ${e} from trunk ${s}?`,default:!1}]);if(!o){t.info("Operation cancelled");return}}let i=await Se();c.start("Removing ACL from trunk..."),await i.removeTrunkAcl(s,e),c.succeed("ACL removed from trunk successfully")}catch(i){c.stop(),t.error(`Failed to remove ACL from trunk: ${i.message}`),process.exit(1)}});ve.addCommand(At);var jn=new qt.Command("credential-lists");jn.description("Manage credential lists for a trunk");jn.command("update").description("Bulk update credential lists for a trunk").argument("<trunk-id>","Trunk ID").argument("<credential-list-ids...>","Credential list IDs to assign (space-separated)").option("--json","Output result as JSON").action(async(s,e,n)=>{try{let i=await Se();c.start(`Updating credential lists for trunk ${s}...`);let o=await i.updateTrunkCredentialLists(s,e);if(c.succeed("Credential lists updated successfully"),n.json)console.log(JSON.stringify(o,null,2));else{t.newline();let r=o?.credentialListIds??[];t.info(`Trunk ${s} now uses ${r.length} credential list(s):`),r.forEach(a=>{t.info(` - ${a}`)})}}catch(i){c.stop(),t.error(`Failed to update credential lists: ${i.message}`),process.exit(1)}});ve.addCommand(jn);Vs.exports=ve});var Gs=R((Ll,Ws)=>{"use strict";var zs=require("commander"),he=h(require("inquirer"));A();E();k();Ge();async function Et(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}async function Rn(s,e){c.start("Looking up endpoint...");let i=(await s.listTrunks()).trunks||[];for(let o of i)if(((await s.listEndpoints(o.id)).endpoints||[]).find(p=>p.id===e))return c.stop(),o.id;throw c.stop(),new Error(`Endpoint ${e} not found`)}function Nn(s){if(t.info(`ID: ${s.id}`),t.info(`Name: ${s.name}`),s.address){let e=s.port?`${s.address}:${s.port}`:s.address;t.info(`Address: ${e}`)}s.transport&&t.info(`Transport: ${s.transport}`),t.info(`Priority: ${s.priority}`),t.info(`Enabled: ${s.enabled!==!1?"yes":"no"}`),s.createTime&&t.info(`Created: ${new Date(s.createTime).toLocaleString()}`),s.updateTime&&t.info(`Updated: ${new Date(s.updateTime).toLocaleString()}`)}var Ye=new zs.Command("endpoints");Ye.description("Manage SIP endpoints");Ye.command("list").description("List all SIP endpoints for a trunk").argument("<trunk-id>","Trunk ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Et();c.start("Fetching SIP endpoints...");let i=await n.listEndpoints(s,{pageSize:e.limit});c.succeed(`Retrieved ${i.endpoints?.length||0} endpoint(s)`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.endpoints&&i.endpoints.length>0?i.endpoints.forEach(o=>{let r=o.enabled!==!1?"":" (disabled)",a=o.port?`${o.address}:${o.port}`:o.address;t.info(`[${o.id}] ${o.name}${r}`),t.info(` Address: ${a||"N/A"}`),t.info(` Priority: ${o.priority}, Transport: ${o.transport||"UDP"}`),t.newline()}):(t.info("No endpoints found for this trunk"),t.newline(),t.info(`Create one with: sinch sip endpoints create ${s}`)))}catch(n){c.stop(),t.error(`Failed to list endpoints: ${n.message}`),process.exit(1)}});Ye.command("get").description("Get a SIP endpoint by ID").argument("<endpoint-id>","Endpoint ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Et(),i=await Rn(n,s);c.start("Fetching endpoint...");let o=await n.getEndpoint(i,s);c.succeed("Endpoint retrieved"),e.json?console.log(JSON.stringify(o,null,2)):(t.newline(),Nn(o))}catch(n){c.stop(),t.error(`Failed to get endpoint: ${n.message}`),process.exit(1)}});Ye.command("create").description("Create a new SIP endpoint").argument("<trunk-id>","Trunk ID to add endpoint to").option("-n, --name <name>","Endpoint name (required)").option("-a, --address <address>","SIP address (IP or hostname, without port)").option("--port <number>","SIP port (default: 5060)",parseInt).option("-t, --transport <transport>","Transport protocol: UDP, TCP, or TLS (default: UDP)").option("-p, --priority <number>","Priority (required, lower = higher priority)",parseInt).option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=e.name,i=e.address,o=e.port,r=e.transport,a=e.priority,l=!e.nonInteractive;n||(l?n=(await he.default.prompt([{type:"input",name:"name",message:"Enter endpoint name:",validate:g=>g?!0:"Endpoint name is required"}])).name:(t.error("Name is required. Use --name <name>"),process.exit(1))),i||(l?i=(await he.default.prompt([{type:"input",name:"address",message:"Enter SIP address (IP or hostname):",validate:g=>g?!0:"SIP address is required"}])).address:(t.error("Address is required. Use --address <address>"),process.exit(1))),o===void 0&&l&&(o=(await he.default.prompt([{type:"input",name:"port",message:"Enter SIP port (default 5060):",default:"5060",filter:g=>g?parseInt(g,10):5060}])).port),a===void 0&&(l?a=(await he.default.prompt([{type:"input",name:"priority",message:"Enter priority (lower = higher priority):",default:"1",filter:g=>parseInt(g,10),validate:g=>{let w=parseInt(g,10);return isNaN(w)?"Please enter a valid number":!0}}])).priority:(t.error("Priority is required. Use --priority <number>"),process.exit(1)));let p=await Et();c.start("Creating SIP endpoint...");let d=await p.createEndpoint(s,{name:n,address:i,port:o,transport:r,priority:a});c.succeed("SIP endpoint created successfully!"),e.json?console.log(JSON.stringify(d,null,2)):(t.newline(),Nn(d))}catch(n){c.stop(),t.error(`Failed to create endpoint: ${n.message}`),process.exit(1)}});Ye.command("update").description("Update a SIP endpoint").argument("<endpoint-id>","Endpoint ID to update").option("-n, --name <name>","New endpoint name").option("-a, --address <address>","New SIP address").option("--port <number>","New SIP port",parseInt).option("-t, --transport <transport>","Transport protocol: UDP, TCP, or TLS").option("-p, --priority <number>","New priority",parseInt).option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Et(),i=await Rn(n,s);c.start("Fetching current endpoint details...");let o=await n.getEndpoint(i,s);c.stop();let r=e.name,a=e.address,l=e.port,p=e.transport,d=e.priority,f=!e.nonInteractive;r||(f?r=(await he.default.prompt([{type:"input",name:"name",message:"Enter endpoint name:",default:o.name,validate:y=>y?!0:"Name is required"}])).name:r=o.name),a||(f?a=(await he.default.prompt([{type:"input",name:"address",message:"Enter SIP address:",default:o.address,validate:y=>y?!0:"SIP address is required"}])).address:a=o.address||""),l===void 0&&(f?l=(await he.default.prompt([{type:"input",name:"port",message:"Enter SIP port:",default:(o.port||5060).toString(),filter:y=>parseInt(y,10)}])).port:l=o.port),d===void 0&&(f?d=(await he.default.prompt([{type:"input",name:"priority",message:"Enter priority:",default:o.priority.toString(),filter:y=>parseInt(y,10)}])).priority:d=o.priority),c.start("Updating SIP endpoint...");let g=await n.updateEndpoint(i,s,{name:r,address:a,port:l,transport:p,priority:d});c.succeed("SIP endpoint updated successfully!"),e.json?console.log(JSON.stringify(g,null,2)):(t.newline(),Nn(g))}catch(n){c.stop(),t.error(`Failed to update endpoint: ${n.message}`),process.exit(1)}});Ye.command("delete").description("Delete a SIP endpoint").argument("<endpoint-id>","Endpoint ID to delete").option("-f, --force","Skip confirmation prompt").action(async(s,e)=>{try{let n=await Et(),i=await Rn(n,s);if(!e.force){let{confirm:o}=await he.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete endpoint ${s}?`,default:!1}]);if(!o){t.info("Deletion cancelled");return}}c.start("Deleting SIP endpoint..."),await n.deleteEndpoint(i,s),c.succeed("SIP endpoint deleted successfully")}catch(n){c.stop(),t.error(`Failed to delete endpoint: ${n.message}`),process.exit(1)}});Ws.exports=Ye});var Qs=R((Kl,Zs)=>{"use strict";var On=require("commander"),K=h(require("inquirer"));A();E();k();Ge();async function ye(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}function Tn(s){t.info(`ID: ${s.id}`),t.info(`Name: ${s.name}`),t.info(`Enabled: ${s.enabled!==!1?"yes":"no"}`),s.createTime&&t.info(`Created: ${new Date(s.createTime).toLocaleString()}`),s.updateTime&&t.info(`Updated: ${new Date(s.updateTime).toLocaleString()}`)}function Ys(s){t.info(`ID: ${s.id}`),s.description&&t.info(`Description: ${s.description}`),s.ipAddress&&t.info(`IP Address: ${s.ipAddress}`),s.range&&t.info(`CIDR Range: ${s.range}`),s.createTime&&t.info(`Created: ${new Date(s.createTime).toLocaleString()}`)}function Ze(s){return/^(\d{1,3}\.){3}\d{1,3}$/.test(s)?s.split(".").every(i=>{let o=parseInt(i,10);return o>=0&&o<=255}):!1}function Mt(s){if(!/^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/.test(s))return!1;let n=s.split("/");if(n.length!==2)return!1;let i=n[0],o=n[1];if(!i||!o)return!1;let r=parseInt(o,10);return Ze(i)&&r>=0&&r<=32}var $e=new On.Command("acls");$e.description("Manage Access Control Lists (ACLs)");$e.command("list").description("List all Access Control Lists").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async s=>{try{let e=await ye();c.start("Fetching ACLs...");let n=await e.listAcls({pageSize:s.limit});c.succeed(`Retrieved ${n.accessControlLists?.length||0} ACL(s)`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.accessControlLists&&n.accessControlLists.length>0?n.accessControlLists.forEach(i=>{let o=i.enabled!==!1?"":" (disabled)";t.info(`[${i.id}] ${i.name}${o}`),t.newline()}):(t.info("No ACLs found"),t.newline(),t.info("Create one with: sinch sip acls create")))}catch(e){c.stop(),t.error(`Failed to list ACLs: ${e.message}`),process.exit(1)}});$e.command("get").description("Get an ACL by ID").argument("<acl-id>","ACL ID to retrieve").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await ye();c.start("Fetching ACL...");let i=await n.getAcl(s);c.succeed("ACL retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Tn(i))}catch(n){c.stop(),t.error(`Failed to get ACL: ${n.message}`),process.exit(1)}});$e.command("create").description("Create a new Access Control List").option("-n, --name <name>","ACL name (required)").option("--enabled","Enable the ACL (default: true)").option("--disabled","Create ACL in disabled state").option("-i, --ip <address>","IP address for initial IP range (required)").option("-r, --range <cidr>","CIDR mask for IP range (default: 32)",parseInt).option("--ip-description <text>","Description for the IP range").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async s=>{try{let e=s.name,n=s.enabled??!s.disabled,i=s.ip,o=s.range,r=s.ipDescription,a=!s.nonInteractive;e||(a?e=(await K.default.prompt([{type:"input",name:"name",message:"Enter ACL name:",validate:g=>g?!0:"ACL name is required"}])).name:(t.error("Name is required. Use --name <name>"),process.exit(1))),s.enabled===void 0&&!s.disabled&&a&&(n=(await K.default.prompt([{type:"confirm",name:"enabled",message:"Enable ACL?",default:!0}])).enabled),i?Ze(i)||(t.error(`Invalid IP address format: ${i}`),process.exit(1)):a?i=(await K.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address for initial IP range (required):",validate:g=>g?Ze(g)?!0:"Invalid IP address format":"At least one IP range is required to create an ACL"}])).ipAddress:(t.error("IP address is required. Use --ip <address>"),process.exit(1)),o===void 0&&a&&(o=(await K.default.prompt([{type:"input",name:"range",message:"Enter CIDR mask (default 32):",default:"32",filter:g=>parseInt(g,10),validate:g=>{let w=parseInt(g,10);return!isNaN(w)&&w>=0&&w<=32?!0:"Please enter a number between 0 and 32"}}])).range),r===void 0&&a&&(r=(await K.default.prompt([{type:"input",name:"description",message:"Enter IP range description (optional):"}])).description||void 0);let l=await ye(),p={ipAddress:i};o!==void 0&&(p.range=o),r&&(p.description=r),c.start("Creating ACL...");let d=await l.createAcl({name:e,enabled:n,ipRanges:[p]});c.succeed("ACL created successfully!"),s.json?console.log(JSON.stringify(d,null,2)):(t.newline(),Tn(d),t.newline(),t.info(`Add an IP range: sinch sip acls ip-ranges add ${d.id}`))}catch(e){c.stop(),t.error(`Failed to create ACL: ${e.message}`),process.exit(1)}});$e.command("update").description("Update an ACL").argument("<acl-id>","ACL ID to update").option("-n, --name <name>","New ACL name").option("--enabled","Enable the ACL").option("--disabled","Disable the ACL").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await ye();c.start("Fetching current ACL details...");let i=await n.getAcl(s);c.stop();let o=e.name,r;e.enabled?r=!0:e.disabled&&(r=!1);let a=!e.nonInteractive;o||(a?o=(await K.default.prompt([{type:"input",name:"name",message:"Enter ACL name:",default:i.name,validate:d=>d?!0:"ACL name is required"}])).name:o=i.name),r===void 0&&(a?r=(await K.default.prompt([{type:"confirm",name:"enabled",message:"Enable ACL?",default:i.enabled??!0}])).enabled:r=i.enabled),c.start("Updating ACL...");let l=await n.updateAcl(s,{name:o,enabled:r});c.succeed("ACL updated successfully!"),e.json?console.log(JSON.stringify(l,null,2)):(t.newline(),Tn(l))}catch(n){c.stop(),t.error(`Failed to update ACL: ${n.message}`),process.exit(1)}});$e.command("delete").description("Delete an ACL").argument("<acl-id>","ACL ID to delete").option("-f, --force","Skip confirmation prompt").action(async(s,e)=>{try{if(!e.force){let{confirm:i}=await K.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete ACL ${s}?`,default:!1}]);if(!i){t.info("Deletion cancelled");return}}let n=await ye();c.start("Deleting ACL..."),await n.deleteAcl(s),c.succeed("ACL deleted successfully")}catch(n){c.stop(),t.error(`Failed to delete ACL: ${n.message}`),process.exit(1)}});$e.command("trunks").description("List trunks using an ACL").argument("<acl-id>","ACL ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await ye();c.start("Fetching trunks...");let i=await n.getAclTrunks(s,{pageSize:e.limit});c.succeed(`Retrieved ${i.trunks?.length||0} trunk(s)`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.trunks&&i.trunks.length>0?i.trunks.forEach(o=>{t.info(`[${o.id}] ${o.name}`),o.hostName&&t.info(` Host: ${o.hostName}`),t.newline()}):t.info("No trunks are using this ACL"))}catch(n){c.stop(),t.error(`Failed to list trunks: ${n.message}`),process.exit(1)}});var ct=new On.Command("ip-ranges");ct.description("Manage IP ranges for ACLs");ct.command("list").description("List IP ranges for an ACL").argument("<acl-id>","ACL ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await ye();c.start("Fetching IP ranges...");let i=await n.listIpRanges(s,{pageSize:e.limit});c.succeed(`Retrieved ${i.ipRanges?.length||0} IP range(s)`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.ipRanges&&i.ipRanges.length>0?i.ipRanges.forEach(o=>{let r=o.range||o.ipAddress||"N/A";t.info(`[${o.id}] ${r}`),o.description&&t.info(` ${o.description}`),t.newline()}):(t.info("No IP ranges found for this ACL"),t.newline(),t.info(`Add one with: sinch sip acls ip-ranges add ${s}`)))}catch(n){c.stop(),t.error(`Failed to list IP ranges: ${n.message}`),process.exit(1)}});ct.command("add").description("Add an IP range to an ACL").argument("<acl-id>","ACL ID").option("-d, --description <description>","Description for the IP range").option("-i, --ip <ip>","Single IP address (e.g., 192.168.1.1)").option("-r, --range <cidr>","CIDR range (e.g., 192.168.1.0/24)").option("--non-interactive","Skip prompts, use defaults for missing options").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=e.description,i=e.ip,o=e.range,r=!e.nonInteractive;i&&o&&(t.error("Cannot specify both --ip and --range. Please provide only one."),process.exit(1)),!i&&!o&&(r?(await K.default.prompt([{type:"list",name:"type",message:"What would you like to add?",choices:[{name:"Single IP address",value:"ip"},{name:"CIDR range",value:"range"}]}])).type==="ip"?i=(await K.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address (e.g., 192.168.1.1):",validate:g=>g?Ze(g)?!0:"Invalid IP address format":"IP address is required"}])).ipAddress:o=(await K.default.prompt([{type:"input",name:"range",message:"Enter CIDR range (e.g., 192.168.1.0/24):",validate:g=>g?Mt(g)?!0:"Invalid CIDR format (e.g., 192.168.1.0/24)":"CIDR range is required"}])).range:(t.error("Either --ip or --range is required"),process.exit(1))),i&&!Ze(i)&&(t.error(`Invalid IP address format: ${i}`),process.exit(1)),o&&!Mt(o)&&(t.error(`Invalid CIDR range format: ${o}. Expected format: 192.168.1.0/24`),process.exit(1)),!n&&r&&(n=(await K.default.prompt([{type:"input",name:"description",message:"Enter description (optional):"}])).description||void 0);let a=await ye();c.start("Adding IP range...");let l={description:n};i?l.ipAddress=i:o&&(l.range=o);let p=await a.addIpRange(s,l);c.succeed("IP range added successfully!"),e.json?console.log(JSON.stringify(p,null,2)):(t.newline(),Ys(p))}catch(n){c.stop(),t.error(`Failed to add IP range: ${n.message}`),process.exit(1)}});ct.command("update").description("Update an IP range").argument("<acl-id>","ACL ID").argument("<ip-range-id>","IP range ID to update").option("-d, --description <description>","New description").option("-i, --ip <ip>","New single IP address").option("-r, --range <cidr>","New CIDR range").option("--non-interactive","Skip prompts, use current values for missing options").option("--json","Output result as JSON").action(async(s,e,n)=>{try{let i=await ye();c.start("Fetching current IP range details...");let o;try{o=await i.getIpRange(s,e)}catch(g){c.stop(),t.error(`IP range ${e} not found in ACL ${s}: ${g.message}`),process.exit(1)}c.stop();let r=n.description,a=n.ip,l=n.range,p=!n.nonInteractive;if(a&&l&&(t.error("Cannot specify both --ip and --range. Please provide only one."),process.exit(1)),r===void 0&&p?r=(await K.default.prompt([{type:"input",name:"description",message:"Enter description:",default:o.description||""}])).description||void 0:r===void 0&&(r=o.description),!a&&!l&&p){let g=o.range||o.ipAddress||"",w=o.range?"range":"ip";(await K.default.prompt([{type:"list",name:"type",message:"Update as:",choices:[{name:"Single IP address",value:"ip"},{name:"CIDR range",value:"range"}],default:w}])).type==="ip"?(a=(await K.default.prompt([{type:"input",name:"ipAddress",message:"Enter IP address:",default:w==="ip"?g:"",validate:$=>$?Ze($)?!0:"Invalid IP address format":"IP address is required"}])).ipAddress,l=void 0):(l=(await K.default.prompt([{type:"input",name:"range",message:"Enter CIDR range:",default:w==="range"?g:"",validate:$=>$?Mt($)?!0:"Invalid CIDR format":"CIDR range is required"}])).range,a=void 0)}else!a&&!l?(a=o.ipAddress,l=o.range):a?l=void 0:l&&(a=void 0);a&&!Ze(a)&&(t.error(`Invalid IP address format: ${a}`),process.exit(1)),l&&!Mt(l)&&(t.error(`Invalid CIDR range format: ${l}`),process.exit(1)),c.start("Updating IP range...");let d={description:r};a?d.ipAddress=a:l&&(d.range=l);let f=await i.updateIpRange(s,e,d);c.succeed("IP range updated successfully!"),n.json?console.log(JSON.stringify(f,null,2)):(t.newline(),Ys(f))}catch(i){c.stop(),t.error(`Failed to update IP range: ${i.message}`),process.exit(1)}});ct.command("delete").description("Delete an IP range").argument("<acl-id>","ACL ID").argument("<ip-range-id>","IP range ID to delete").option("-f, --force","Skip confirmation prompt").action(async(s,e,n)=>{try{if(!n.force){let{confirm:o}=await K.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete IP range ${e}?`,default:!1}]);if(!o){t.info("Deletion cancelled");return}}let i=await ye();c.start("Deleting IP range..."),await i.deleteIpRange(s,e),c.succeed("IP range deleted successfully")}catch(i){c.stop(),t.error(`Failed to delete IP range: ${i.message}`),process.exit(1)}});$e.addCommand(ct);Zs.exports=$e});var to=R((Yl,eo)=>{"use strict";var Xs=require("commander");A();E();k();Ge();async function Jt(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}function Fn(s){t.info(`ISO Code: ${s.isoCode}`),t.info(`Country: ${s.name}`),t.info(`Continent: ${s.continent}`),t.info(`Dialing Codes: ${s.countryDialingCodes.join(", ")}`),t.info(`Status: ${s.enabled?"enabled":"disabled"}`)}var lt=new Xs.Command("countries");lt.description("Manage country permissions for dialing");lt.command("list").description("List all country permissions").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async s=>{try{let e=await Jt();c.start("Fetching country permissions...");let n=await e.listCountryPermissions({pageSize:s.limit});c.succeed(`Retrieved ${n.countryPermissions?.length||0} country permission(s)`),s.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.countryPermissions&&n.countryPermissions.length>0?([...n.countryPermissions].sort((o,r)=>o.isoCode.localeCompare(r.isoCode)).forEach(o=>{let r=o.enabled?"\u2713 enabled":"\u2717 disabled",a=o.name.padEnd(30);t.info(`${o.isoCode.padEnd(4)} ${a} ${r}`)}),t.newline(),t.info("Enable a country: sinch sip countries enable <iso-code>"),t.info("Disable a country: sinch sip countries disable <iso-code>")):t.info("No country permissions found"))}catch(e){c.stop(),t.error(`Failed to list country permissions: ${e.message}`),process.exit(1)}});lt.command("get").description("Get a specific country permission by ISO code").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Jt();c.start("Fetching country permission...");let i=await n.getCountryPermission(s.toUpperCase());c.succeed("Country permission retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Fn(i))}catch(n){c.stop(),t.error(`Failed to get country permission: ${n.message}`),process.exit(1)}});lt.command("enable").description("Enable a country for dialing").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Jt();c.start(`Enabling country ${s.toUpperCase()}...`);let i=await n.updateCountryPermission(s.toUpperCase(),!0);c.succeed(`Country ${s.toUpperCase()} enabled for dialing`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Fn(i),t.newline(),t.info(`Country ${s.toUpperCase()} is now enabled for dialing`))}catch(n){c.stop(),t.error(`Failed to enable country: ${n.message}`),process.exit(1)}});lt.command("disable").description("Disable a country for dialing").argument("<iso-code>","ISO country code (e.g., US, CA, *)").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Jt();c.start(`Disabling country ${s.toUpperCase()}...`);let i=await n.updateCountryPermission(s.toUpperCase(),!1);c.succeed(`Country ${s.toUpperCase()} disabled for dialing`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Fn(i),t.newline(),t.info(`Country ${s.toUpperCase()} is now disabled for dialing`))}catch(n){c.stop(),t.error(`Failed to disable country: ${n.message}`),process.exit(1)}});eo.exports=lt});var so=R((nd,io)=>{"use strict";var no=require("commander");A();E();k();Ge();async function Wr(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}var Ln=new no.Command("credential-lists");Ln.description("Manage credential list relationships");Ln.command("trunks").description("Get trunks using a credential list").argument("<credential-list-id>","Credential list ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await Wr();c.start("Fetching trunks using credential list...");let i=await n.getCredentialListTrunks(s,{pageSize:e.limit});c.succeed(`Retrieved ${i.trunks?.length||0} trunk(s)`),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.trunks&&i.trunks.length>0?(t.info(`Trunks using credential list ${s}:`),t.newline(),i.trunks.forEach(o=>{t.info(`[${o.id}] ${o.name}`),o.hostName&&t.info(` Host: ${o.hostName}`),t.info(` Caller ID: ${o.enableCallerId?"enabled":"disabled"}`),t.newline()}),i.totalItems&&t.info(`Total: ${i.totalItems} trunk(s)`)):t.info("No trunks found using this credential list"))}catch(n){c.stop(),t.error(`Failed to get trunks for credential list: ${n.message}`),process.exit(1)}});io.exports=Ln});var co=R((dd,xt)=>{"use strict";var oo=require("commander");A();E();k();Ge();async function ro(){await u.load(),await u.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=u.getApiConfig();return new te({projectId:e.projectId,credentials:e.credentials})}function ao(s){if(!s){let n=new Date;return`>=${new Date(n.getTime()-1440*60*1e3).toISOString()}`}if(s.startsWith(">=")||s.startsWith("<=")||s.startsWith(">")||s.startsWith("<"))return s;let e=s.split("-");if(e.length===1&&e[0]){let n=e[0];return`>=${n}-01-01T00:00:00Z,<=${n}-12-31T23:59:59Z`}else if(e.length===2&&e[0]&&e[1]){let n=e[0],i=e[1],o=new Date(parseInt(n),parseInt(i),0).getDate();return`>=${n}-${i}-01T00:00:00Z,<=${n}-${i}-${o.toString().padStart(2,"0")}T23:59:59Z`}else return`>=${s}T00:00:00Z,<=${s}T23:59:59Z`}function Bt(s){if(s===void 0||s===0)return"-";let e=Math.floor(s/3600),n=Math.floor(s%3600/60),i=s%60;return e>0?`${e}h ${n}m ${i}s`:n>0?`${n}m ${i}s`:`${i}s`}function _n(s){return!s||!s.amount?"-":`${parseFloat(s.amount).toFixed(4)} ${s.currencyCode}`}function Gr(s,e=!1){t.info(`Call ID: ${s.callId}`),t.info(`From: ${s.from}`),t.info(`To: ${s.to}`),t.info(`Direction: ${s.direction}`),t.info(`Status: ${s.callResult||"In Progress"}`),(e||s.durationSeconds)&&t.info(`Duration: ${Bt(s.durationSeconds)}`),(e||s.billingDurationSeconds)&&t.info(`Billing Duration: ${Bt(s.billingDurationSeconds)}`),s.price&&t.info(`Cost: ${_n(s.price)}`),t.info(`Trunk ID: ${s.trunkId}`),t.info(`Created: ${new Date(s.createTime).toLocaleString()}`),s.answerTime&&t.info(`Answered: ${new Date(s.answerTime).toLocaleString()}`),s.endTime&&t.info(`Ended: ${new Date(s.endTime).toLocaleString()}`)}var Kt=new oo.Command("calls");Kt.description("View call history and details");Kt.command("list").description("List calls with filtering options").option("--from <number>","Filter by originating phone number (supports partial matching)").option("--to <number>","Filter by destination phone number (supports partial matching)").option("--trunk-id <id>","Filter by trunk ID").option("--direction <direction>","Filter by direction (INBOUND or OUTBOUND)").option("--result <result>","Filter by call result (COMPLETED, NO_ANSWER, CANCEL, BUSY, FAILED)").option("--date <date>","Filter by date (YYYY-MM-DD, YYYY-MM, or YYYY). Defaults to last 24 hours.").option("--page <number>","Page number",parseInt).option("--page-size <number>","Number of results per page (max 1000)",parseInt,100).option("--json","Output result as JSON").action(async s=>{try{let e=await ro(),n={pageSize:s.pageSize};if(s.from&&(n.from=s.from),s.to&&(n.to=s.to),s.trunkId&&(n.trunkId=s.trunkId),s.direction&&(["INBOUND","OUTBOUND"].includes(s.direction.toUpperCase())||(t.error("Invalid direction. Must be INBOUND or OUTBOUND."),process.exit(1)),n.direction=s.direction.toUpperCase()),s.result){let o=["COMPLETED","NO_ANSWER","CANCEL","BUSY","FAILED"];o.includes(s.result.toUpperCase())||(t.error(`Invalid result. Must be one of: ${o.join(", ")}`),process.exit(1)),n.callResult=s.result.toUpperCase()}s.page&&(n.page=s.page),n.createTime=ao(s.date),c.start("Fetching calls...");let i=await e.findCalls(n);c.succeed(`Retrieved ${i.calls?.length||0} call(s)`),s.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.calls&&i.calls.length>0?(i.calls.forEach(o=>{let r=Bt(o.durationSeconds),a=o.callResult||"In Progress",l=_n(o.price);t.info(`${o.callId}`),t.info(` ${o.from} \u2192 ${o.to}`),t.info(` ${o.direction} | ${a} | ${r} | ${l}`),t.info(` ${new Date(o.createTime).toLocaleString()}`),t.newline()}),i.totalItems&&(t.info(`Total: ${i.totalItems} call(s)`),i.pageNumber&&t.info(`Page: ${i.pageNumber}`))):(t.info("No calls found matching the filters"),t.newline(),t.info("Try adjusting your filters or date range.")))}catch(e){c.fail("Failed to fetch calls"),t.error(e.message),process.exit(1)}});Kt.command("get").description("Get details of a specific call").argument("<call-id>","Call ID").option("--json","Output result as JSON").action(async(s,e)=>{try{let n=await ro();c.start(`Fetching call ${s}...`);let i=await n.getCall(s);c.succeed("Call retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),Gr(i,!0))}catch(n){c.fail("Failed to get call"),t.error(n.message),process.exit(1)}});xt.exports=Kt;xt.exports.parseDateFilter=ao;xt.exports.formatDuration=Bt;xt.exports.formatPrice=_n});var uo=R((pd,po)=>{"use strict";var lo=require("commander"),Yr=Hs(),Zr=Gs(),Qr=Qs(),Xr=to(),ea=so(),ta=co(),Ne=new lo.Command("sip");Ne.description("Manage Elastic SIP Trunking resources");Ne.addCommand(Yr);Ne.addCommand(Zr);Ne.addCommand(Qr);Ne.addCommand(Xr);Ne.addCommand(ea);Ne.addCommand(ta);po.exports=Ne});async function re(s){let e={};for(let n of s){if(n.when!==void 0&&!(typeof n.when=="function"?await n.when(e):n.when))continue;let i;switch(n.type){case"input":{let o=await(0,ue.input)({message:n.message,default:n.default,validate:n.validate});n.filter&&(o=n.filter(o)),i=o;break}case"password":i=await(0,ue.password)({message:n.message,validate:n.validate});break;case"confirm":i=await(0,ue.confirm)({message:n.message,default:n.default});break;case"list":i=await(0,ue.select)({message:n.message,choices:(n.choices||[]).map(o=>typeof o=="string"?{name:o,value:o}:o),default:n.default,pageSize:n.pageSize});break;case"checkbox":i=await(0,ue.checkbox)({message:n.message,choices:(n.choices||[]).map(o=>typeof o=="string"?{name:o,value:o}:o),pageSize:n.pageSize});break;default:throw new Error(`Unsupported prompt type: ${n.type}`)}e[n.name]=i}return e}var ue,fo=Q(()=>{"use strict";ue=require("@inquirer/prompts")});var go,Un,qn,mo=Q(()=>{"use strict";go=require("@sinch/sdk-core");k();Un=class{client=null;initialized=!1;async initialize(){if(!(this.initialized&&this.client))try{await u.load();let e=await u.getCredentials();if(!e)throw new Error("Not authenticated. Please run: sinch auth login");this.client=new go.SinchClient({projectId:e.projectId,keyId:e.keyId,keySecret:e.keySecret}),this.initialized=!0}catch(e){throw new Error(`Failed to initialize fax client: ${e.message}`)}}async getClient(){return this.initialized||await this.initialize(),this.client}isInitialized(){return this.initialized}async getServiceConfig(){return await u.load(),{serviceId:u.getFaxServiceId(),senderNumber:u.getFaxSenderNumber()}}async validateConfig(){let e=await this.getServiceConfig(),n=[];return e.serviceId||n.push("fax service ID (set with: sinch config set fax service-id <id>)"),{valid:n.length===0,missing:n}}},qn=new Un});var vo={};ut(vo,{FaxManager:()=>Vt,default:()=>ia,getFaxClient:()=>bo,getFaxManager:()=>Ie});async function bo(){try{return await u.load(),await u.hasCredentials()||(t.error("Not authenticated. Please run: sinch auth login"),process.exit(1)),await qn.initialize(),await qn.getClient()}catch(s){t.error(`Failed to initialize fax client: ${s.message}`),process.exit(1)}}async function Ie(){let s=await bo(),e=await u.getFaxCredentials();return new Vt(s,e)}async function na(){let s=yo.platform();try{if(s==="darwin")return(0,Dt.execSync)(`osascript -e '${`
121
121
  set fileTypes to {"pdf", "tif", "tiff", "doc", "docx", "txt", "html", "htm"}
122
122
  set theFile to choose file with prompt "Select a file to send:" of type fileTypes
123
123
  return POSIX path of theFile
@@ -130,7 +130,7 @@ ${p.display_name||"No name"}`)),p.channel_identities&&p.channel_identities.lengt
130
130
  if ($result -eq 'OK') {
131
131
  Write-Output $dialog.FileName
132
132
  }
133
- `.replace(/"/g,'\\"')}"`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null;try{return(0,Dt.execSync)(`zenity --file-selection --title="Select a file to send" --file-filter='Fax Files | *.pdf *.tif *.tiff *.doc *.docx *.txt *.html *.htm' 2>/dev/null`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return(0,Dt.execSync)('kdialog --getopenfilename ~ "*.pdf *.tif *.tiff *.doc *.docx *.txt *.html *.htm|Fax Files" 2>/dev/null',{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null}}catch{return null}}async function So(){let{inputMethod:s}=await re([{type:"list",name:"inputMethod",message:"How would you like to select the file?",choices:[{name:"\u{1F4C1} Browse files",value:"browse"},{name:"\u2328\uFE0F Enter file path manually",value:"manual"}]}]);if(s==="browse"){let e=await ta();if(e)return t.info(`Selected: ${e}`),e;{t.warn("File selection cancelled or unavailable, please enter path manually");let{file:n}=await re([{type:"input",name:"file",message:"Enter the path to the file you want to send:",validate:i=>!i||i.trim().length===0?"File path is required":!0}]);return n}}else{let{file:e}=await re([{type:"input",name:"file",message:"Enter the path to the file you want to send:",validate:n=>!n||n.trim().length===0?"File path is required":!0}]);return e}}var ho,dt,Qe,yo,Dt,wo,Co,Vt,Oe,na,$o=Q(()=>{"use strict";ho=require("commander");A();E();fo();mo();k();dt=h(require("fs-extra")),Qe=h(require("path")),yo=h(require("os")),Dt=require("child_process"),wo=h(require("form-data")),Co=h(require("axios")),Vt=class{credentials;constructor(e,n){this.credentials=n}async validateFile(e){let n=Qe.resolve(e);if(!await dt.pathExists(n))throw new Error(`File not found: ${e}`);let o=await dt.stat(n);if(!o.isFile())throw new Error(`Path is not a file: ${e}`);let r=Qe.extname(n).toLowerCase(),a=[".pdf",".tif",".tiff",".doc",".docx",".txt",".html",".htm"];if(!a.includes(r))throw new Error(`Unsupported file type: ${r}. Supported types: ${a.join(", ")}`);let l=20*1024*1024;if(o.size>l)throw new Error(`File too large: ${(o.size/1024/1024).toFixed(2)}MB. Maximum size: 20MB`)}validateUrl(e){try{let n=new URL(e);if(!["http:","https:"].includes(n.protocol))throw new Error("URL must use HTTP or HTTPS protocol")}catch(n){throw new Error(`Invalid URL: ${n.message}`)}}async sendFax(e){let{to:n,from:i,file:o,contentUrl:r,serviceId:a}=e;if(!o&&!r)throw new Error("Either --file or --content-url must be provided");let l=a||u.getFaxServiceId();if(!l)throw new Error("Fax service ID is required. Set it with: sinch config --set fax serviceID=<id>");let p=i||u.getFaxSenderNumber();if(o&&await this.validateFile(o),r){let y=Array.isArray(r)?r:[r];for(let v of y)this.validateUrl(v)}let d=new wo.default;if(d.append("to",n),p&&d.append("from",p),d.append("serviceId",l),o){let y=Qe.resolve(o),v=dt.createReadStream(y),$=Qe.basename(y);d.append("file",v,$)}r&&(Array.isArray(r)?d.append("contentUrl",r.join(",")):d.append("contentUrl",r));let f=this.credentials||await u.getCredentials();if(!f)throw new Error("Not authenticated. Please run: sinch auth login");let w=`https://fax.api.sinch.com/v3/projects/${f.projectId}/faxes`;try{return(await Co.default.post(w,d,{headers:{...d.getHeaders()},auth:{username:f.keyId,password:f.keySecret},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(y){if(y.response){let v=y.response.status,$=y.response.data,P=`HTTP ${v}`;if(y.response.statusText&&(P+=` ${y.response.statusText}`),$)if(typeof $=="string"&&$.trim()?P+=`: ${$}`:$.message&&(P+=`: ${$.message}`),$.details&&Array.isArray($.details))for(let C of $.details)if(C.fieldViolations&&Array.isArray(C.fieldViolations)){P+=`
133
+ `.replace(/"/g,'\\"')}"`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null;try{return(0,Dt.execSync)(`zenity --file-selection --title="Select a file to send" --file-filter='Fax Files | *.pdf *.tif *.tiff *.doc *.docx *.txt *.html *.htm' 2>/dev/null`,{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return(0,Dt.execSync)('kdialog --getopenfilename ~ "*.pdf *.tif *.tiff *.doc *.docx *.txt *.html *.htm|Fax Files" 2>/dev/null',{encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim()||null}}catch{return null}}async function So(){let{inputMethod:s}=await re([{type:"list",name:"inputMethod",message:"How would you like to select the file?",choices:[{name:"\u{1F4C1} Browse files",value:"browse"},{name:"\u2328\uFE0F Enter file path manually",value:"manual"}]}]);if(s==="browse"){let e=await na();if(e)return t.info(`Selected: ${e}`),e;{t.warn("File selection cancelled or unavailable, please enter path manually");let{file:n}=await re([{type:"input",name:"file",message:"Enter the path to the file you want to send:",validate:i=>!i||i.trim().length===0?"File path is required":!0}]);return n}}else{let{file:e}=await re([{type:"input",name:"file",message:"Enter the path to the file you want to send:",validate:n=>!n||n.trim().length===0?"File path is required":!0}]);return e}}var ho,dt,Qe,yo,Dt,wo,Co,Vt,Oe,ia,$o=Q(()=>{"use strict";ho=require("commander");A();E();fo();mo();k();dt=h(require("fs-extra")),Qe=h(require("path")),yo=h(require("os")),Dt=require("child_process"),wo=h(require("form-data")),Co=h(require("axios")),Vt=class{credentials;constructor(e,n){this.credentials=n}async validateFile(e){let n=Qe.resolve(e);if(!await dt.pathExists(n))throw new Error(`File not found: ${e}`);let o=await dt.stat(n);if(!o.isFile())throw new Error(`Path is not a file: ${e}`);let r=Qe.extname(n).toLowerCase(),a=[".pdf",".tif",".tiff",".doc",".docx",".txt",".html",".htm"];if(!a.includes(r))throw new Error(`Unsupported file type: ${r}. Supported types: ${a.join(", ")}`);let l=20*1024*1024;if(o.size>l)throw new Error(`File too large: ${(o.size/1024/1024).toFixed(2)}MB. Maximum size: 20MB`)}validateUrl(e){try{let n=new URL(e);if(!["http:","https:"].includes(n.protocol))throw new Error("URL must use HTTP or HTTPS protocol")}catch(n){throw new Error(`Invalid URL: ${n.message}`)}}async sendFax(e){let{to:n,from:i,file:o,contentUrl:r,serviceId:a}=e;if(!o&&!r)throw new Error("Either --file or --content-url must be provided");let l=a||u.getFaxServiceId();if(!l)throw new Error("Fax service ID is required. Set it with: sinch config --set fax serviceID=<id>");let p=i||u.getFaxSenderNumber();if(o&&await this.validateFile(o),r){let y=Array.isArray(r)?r:[r];for(let v of y)this.validateUrl(v)}let d=new wo.default;if(d.append("to",n),p&&d.append("from",p),d.append("serviceId",l),o){let y=Qe.resolve(o),v=dt.createReadStream(y),$=Qe.basename(y);d.append("file",v,$)}r&&(Array.isArray(r)?d.append("contentUrl",r.join(",")):d.append("contentUrl",r));let f=this.credentials||await u.getCredentials();if(!f)throw new Error("Not authenticated. Please run: sinch auth login");let w=`https://fax.api.sinch.com/v3/projects/${f.projectId}/faxes`;try{return(await Co.default.post(w,d,{headers:{...d.getHeaders()},auth:{username:f.keyId,password:f.keySecret},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(y){if(y.response){let v=y.response.status,$=y.response.data,P=`HTTP ${v}`;if(y.response.statusText&&(P+=` ${y.response.statusText}`),$)if(typeof $=="string"&&$.trim()?P+=`: ${$}`:$.message&&(P+=`: ${$.message}`),$.details&&Array.isArray($.details))for(let C of $.details)if(C.fieldViolations&&Array.isArray(C.fieldViolations)){P+=`
134
134
 
135
135
  Validation Errors:`;for(let S of C.fieldViolations)P+=`
136
136
  \u2022 ${S.field}: ${S.description}`}else C.message&&(P+=`
@@ -147,9 +147,9 @@ Validation Errors:`;for(let S of C.fieldViolations)P+=`
147
147
  \u2192 Validation failed. Common issues:`,P+=`
148
148
  \u2022 Phone numbers must be in E.164 format (e.g., +12025551234)`,P+=`
149
149
  \u2022 Service ID must be valid`,P+=`
150
- \u2022 From number must be a number that belongs to your project`)),new Error(P)}else throw y.request?new Error(`No response from Fax API: ${y.message}`):new Error(`Failed to send fax: ${y.message}`)}}async listFaxes(e){let{serviceId:n}=e;if(!(n||u.getFaxServiceId()))throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>");return[]}async getFax(e,n){let i=n||u.getFaxServiceId();if(!i)throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>");return{id:e,status:"completed",serviceId:i}}async cancelFax(e,n){if(!(n||u.getFaxServiceId()))throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>")}displayFaxDetails(e){t.newline(),t.info("Fax Details:"),t.info(`ID: ${e.id}`),t.info(`To: ${e.to||"N/A"}`),t.info(`From: ${e.from||"N/A"}`),t.info(`Status: ${e.status||"N/A"}`),t.info(`Created: ${e.createdAt||e.created_at||"N/A"}`),t.newline()}};Oe=new ho.Command("fax");Oe.description("Manage Sinch Fax API");Oe.action(async()=>{try{t.newline();let{action:s}=await re([{type:"list",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F4E4} Send a fax",value:"send"},{name:"\u{1F4CB} List faxes",value:"list"},{name:"\u{1F50D} Get fax details",value:"get"},{name:"\u{1F6AB} Cancel a fax",value:"cancel"},{name:"\u{1F4CA} Check status",value:"status"}]}]);if(s==="send"){let e=await re([{type:"input",name:"to",message:"Who would you like to send this fax to?",validate:a=>!a||a.trim().length===0?"Recipient fax number is required":/^\+?[1-9]\d{1,14}$/.test(a.trim())?!0:"Please enter a valid phone number in E.164 format (e.g., +12025551234)"},{type:"list",name:"contentType",message:"How would you like to provide the fax content?",choices:[{name:"File",value:"file"},{name:"URL",value:"url"}]}]),n,i;e.contentType==="file"?n=await So():i=(await re([{type:"input",name:"contentUrl",message:"Enter the URL of the content to send:",validate:l=>{if(!l||l.trim().length===0)return"Content URL is required";try{return new URL(l),!0}catch{return"Please enter a valid URL (e.g., https://example.com/document.pdf)"}}}])).contentUrl;let o=await Ie();t.newline(),c.start("Sending fax...");let r=await o.sendFax({to:e.to,file:n,contentUrl:i});c.succeed("Fax sent successfully!"),t.newline(),t.info("Fax Details:"),t.info(`ID: ${r.id}`),t.info(`To: ${r.to}`),t.info(`From: ${r.from}`),t.info(`Status: ${r.status}`),t.info(`Service ID: ${r.serviceId}`),t.info(`Created: ${r.createTime}`),t.newline(),t.info('\u{1F4A1} Tip: Use "sinch fax get <fax-id>" to check fax status'),t.newline()}else if(s==="list")await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline();else if(s==="get"){let{faxId:e}=await re([{type:"input",name:"faxId",message:"Enter the fax ID:",validate:n=>!n||n.trim().length===0?"Fax ID is required":!0}]);await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline()}else if(s==="cancel"){let{faxId:e}=await re([{type:"input",name:"faxId",message:"Enter the fax ID to cancel:",validate:n=>!n||n.trim().length===0?"Fax ID is required":!0}]);await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline()}else if(s==="status"){await u.load();let e=await u.hasFaxCredentials(),n=u.getFaxPublicCredentialInfo(),i=u.getFaxServiceId(),o=u.getFaxSenderNumber();t.newline(),e?(t.info("\u2713 Fax service authenticated"),t.info(`Project ID: ${n.projectId||"N/A"}`),t.info(`Key ID: ${n.keyId||"N/A"}`),t.info(`Service ID: ${i||"Not configured"}`),t.info(`Sender Number: ${o||"Not configured"}`),t.info(`Source: ${n.source}`)):(t.info("\u2717 Not authenticated"),t.info("Run: sinch auth login")),t.newline()}}catch(s){c.fail("Operation failed"),t.error(s.message),process.exit(1)}});Oe.command("send").description("Send a fax").option("-t, --to <number>","Recipient fax number").option("-f, --file <path>","Path to file to send").option("-u, --content-url <url>","URL to content to send",(s,e)=>e?[...Array.isArray(e)?e:[e],s]:s).option("--from <number>","Sender fax number (uses default if not specified)").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async s=>{try{let e=s.to,n=s.file,i=s.contentUrl;s.json?(e||(console.error(JSON.stringify({error:"Recipient number (-t, --to) is required in JSON mode"},null,2)),process.exit(1)),!n&&!i&&(console.error(JSON.stringify({error:"Either --file or --content-url must be provided"},null,2)),process.exit(1))):(e||(e=(await re([{type:"input",name:"to",message:"Who would you like to send this fax to?",validate:l=>!l||l.trim().length===0?"Recipient fax number is required":/^\+?[1-9]\d{1,14}$/.test(l.trim())?!0:"Please enter a valid phone number in E.164 format (e.g., +12025551234)"}])).to),!n&&!i&&((await re([{type:"list",name:"contentType",message:"How would you like to provide the fax content?",choices:[{name:"File",value:"file"},{name:"URL",value:"url"}]}])).contentType==="file"?n=await So():i=(await re([{type:"input",name:"contentUrl",message:"Enter the URL of the content to send:",validate:p=>{if(!p||p.trim().length===0)return"Content URL is required";try{return new URL(p),!0}catch{return"Please enter a valid URL (e.g., https://example.com/document.pdf)"}}}])).contentUrl));let o=await Ie();s.json||(t.newline(),c.start("Sending fax..."));let r=await o.sendFax({to:e,from:s.from,file:n,contentUrl:i,serviceId:s.serviceId});s.json?console.log(JSON.stringify(r,null,2)):(c.succeed("Fax sent successfully!"),t.newline(),t.info("Fax Details:"),t.info(`ID: ${r.id}`),t.info(`To: ${r.to}`),t.info(`From: ${r.from}`),t.info(`Status: ${r.status}`),t.info(`Service ID: ${r.serviceId}`),t.info(`Created: ${r.createTime}`),t.newline(),t.info('\u{1F4A1} Tip: Use "sinch fax get <fax-id>" to check fax status'),t.newline())}catch(e){s.json?console.error(JSON.stringify({error:e.message},null,2)):(c.fail("Failed to send fax"),t.error(e.message)),process.exit(1)}});Oe.command("list").description("List sent faxes").option("-l, --limit <number>","Maximum number of faxes to return","10").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async s=>{try{await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline()}catch(e){t.error(`Failed to list faxes: ${e.message}`),process.exit(1)}});Oe.command("get").description("Get fax details").argument("<fax-id>","Fax ID").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async(s,e)=>{try{await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline()}catch(n){t.error(`Failed to get fax: ${n.message}`),process.exit(1)}});Oe.command("cancel").description("Cancel a pending fax").argument("<fax-id>","Fax ID to cancel").option("--service-id <id>","Fax service ID (uses default if not specified)").action(async(s,e)=>{try{await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline()}catch(n){t.error(`Failed to cancel fax: ${n.message}`),process.exit(1)}});Oe.command("status").description("Check fax service authentication status").action(async()=>{try{await u.load();let s=await u.hasFaxCredentials(),e=u.getFaxPublicCredentialInfo(),n=u.getFaxServiceId(),i=u.getFaxSenderNumber();t.newline(),s?(t.info("\u2713 Fax service authenticated"),t.info(`Project ID: ${e.projectId||"N/A"}`),t.info(`Key ID: ${e.keyId||"N/A"}`),t.info(`Service ID: ${n||"Not configured"}`),t.info(`Sender Number: ${i||"Not configured"}`),t.info(`Source: ${e.source}`)):(t.info("\u2717 Not authenticated"),t.info("Run: sinch auth login")),t.newline()}catch(s){t.error(`Failed to check status: ${s.message}`),process.exit(1)}});na=Oe});var Mn=require("commander"),m=h(require("chalk")),Te=h(require("fs-extra")),Ht=h(require("path")),Jn=h(require("os")),Io=require("child_process");var _e=h(require("fs")),Wt=h(require("path")),Gt=h(require("chalk")),Ro=18e5,No="https://registry.npmjs.org/@sinch/cli";function Oo(){if(process.platform!=="win32")try{if(_e.default.existsSync("/.dockerenv"))return!0;let s=_e.default.readFileSync("/proc/1/cgroup","utf8");return s.includes("docker")||s.includes("containerd")}catch{return!1}return!!process.env.DOCKER_CONTAINER}function To(){return!!process.env.CI}function Fo(){return Oo()||To()}function Lo(s){return s.includes("-dev.")?"dev":parseInt(s.split(".")[0]||"0")>=1?"latest":"beta"}function _o(s){try{if(!_e.default.existsSync(s))return!0;let e=parseInt(_e.default.readFileSync(s,"utf8"));return Date.now()-e>Ro}catch{return!0}}function Uo(s,e){let n=s.replace(/^v/,"").split("-")[0]||"0.0.0",i=e.replace(/^v/,"").split("-")[0]||"0.0.0",o=n.split(".").map(a=>parseInt(a)||0),r=i.split(".").map(a=>parseInt(a)||0);for(let a=0;a<3;a++){let l=o[a]||0,p=r[a]||0;if(p>l)return!0;if(p<l)return!1}if(s.includes("-dev.")&&e.includes("-dev.")){let a=parseInt(s.split("-dev.")[1]||"0");return parseInt(e.split("-dev.")[1]||"0")>a}return!1}async function qo(s){try{let e=await fetch(No,{signal:AbortSignal.timeout(3e3)});return e.ok&&(await e.json())["dist-tags"]?.[s]||null}catch{return null}}async function Mo(s,e){let n=zt().version,i=Lo(n);try{let o=await qo(i);if(!o)return;Uo(n,o)&&(console.log(Gt.default.yellow(`
150
+ \u2022 From number must be a number that belongs to your project`)),new Error(P)}else throw y.request?new Error(`No response from Fax API: ${y.message}`):new Error(`Failed to send fax: ${y.message}`)}}async listFaxes(e){let{serviceId:n}=e;if(!(n||u.getFaxServiceId()))throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>");return[]}async getFax(e,n){let i=n||u.getFaxServiceId();if(!i)throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>");return{id:e,status:"completed",serviceId:i}}async cancelFax(e,n){if(!(n||u.getFaxServiceId()))throw new Error("Fax service ID is required. Set it with: sinch config set fax service-id <id>")}displayFaxDetails(e){t.newline(),t.info("Fax Details:"),t.info(`ID: ${e.id}`),t.info(`To: ${e.to||"N/A"}`),t.info(`From: ${e.from||"N/A"}`),t.info(`Status: ${e.status||"N/A"}`),t.info(`Created: ${e.createdAt||e.created_at||"N/A"}`),t.newline()}};Oe=new ho.Command("fax");Oe.description("Manage Sinch Fax API");Oe.action(async()=>{try{t.newline();let{action:s}=await re([{type:"list",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F4E4} Send a fax",value:"send"},{name:"\u{1F4CB} List faxes",value:"list"},{name:"\u{1F50D} Get fax details",value:"get"},{name:"\u{1F6AB} Cancel a fax",value:"cancel"},{name:"\u{1F4CA} Check status",value:"status"}]}]);if(s==="send"){let e=await re([{type:"input",name:"to",message:"Who would you like to send this fax to?",validate:a=>!a||a.trim().length===0?"Recipient fax number is required":/^\+?[1-9]\d{1,14}$/.test(a.trim())?!0:"Please enter a valid phone number in E.164 format (e.g., +12025551234)"},{type:"list",name:"contentType",message:"How would you like to provide the fax content?",choices:[{name:"File",value:"file"},{name:"URL",value:"url"}]}]),n,i;e.contentType==="file"?n=await So():i=(await re([{type:"input",name:"contentUrl",message:"Enter the URL of the content to send:",validate:l=>{if(!l||l.trim().length===0)return"Content URL is required";try{return new URL(l),!0}catch{return"Please enter a valid URL (e.g., https://example.com/document.pdf)"}}}])).contentUrl;let o=await Ie();t.newline(),c.start("Sending fax...");let r=await o.sendFax({to:e.to,file:n,contentUrl:i});c.succeed("Fax sent successfully!"),t.newline(),t.info("Fax Details:"),t.info(`ID: ${r.id}`),t.info(`To: ${r.to}`),t.info(`From: ${r.from}`),t.info(`Status: ${r.status}`),t.info(`Service ID: ${r.serviceId}`),t.info(`Created: ${r.createTime}`),t.newline(),t.info('\u{1F4A1} Tip: Use "sinch fax get <fax-id>" to check fax status'),t.newline()}else if(s==="list")await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline();else if(s==="get"){let{faxId:e}=await re([{type:"input",name:"faxId",message:"Enter the fax ID:",validate:n=>!n||n.trim().length===0?"Fax ID is required":!0}]);await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline()}else if(s==="cancel"){let{faxId:e}=await re([{type:"input",name:"faxId",message:"Enter the fax ID to cancel:",validate:n=>!n||n.trim().length===0?"Fax ID is required":!0}]);await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline()}else if(s==="status"){await u.load();let e=await u.hasFaxCredentials(),n=u.getFaxPublicCredentialInfo(),i=u.getFaxServiceId(),o=u.getFaxSenderNumber();t.newline(),e?(t.info("\u2713 Fax service authenticated"),t.info(`Project ID: ${n.projectId||"N/A"}`),t.info(`Key ID: ${n.keyId||"N/A"}`),t.info(`Service ID: ${i||"Not configured"}`),t.info(`Sender Number: ${o||"Not configured"}`),t.info(`Source: ${n.source}`)):(t.info("\u2717 Not authenticated"),t.info("Run: sinch auth login")),t.newline()}}catch(s){c.fail("Operation failed"),t.error(s.message),process.exit(1)}});Oe.command("send").description("Send a fax").option("-t, --to <number>","Recipient fax number").option("-f, --file <path>","Path to file to send").option("-u, --content-url <url>","URL to content to send",(s,e)=>e?[...Array.isArray(e)?e:[e],s]:s).option("--from <number>","Sender fax number (uses default if not specified)").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async s=>{try{let e=s.to,n=s.file,i=s.contentUrl;s.json?(e||(console.error(JSON.stringify({error:"Recipient number (-t, --to) is required in JSON mode"},null,2)),process.exit(1)),!n&&!i&&(console.error(JSON.stringify({error:"Either --file or --content-url must be provided"},null,2)),process.exit(1))):(e||(e=(await re([{type:"input",name:"to",message:"Who would you like to send this fax to?",validate:l=>!l||l.trim().length===0?"Recipient fax number is required":/^\+?[1-9]\d{1,14}$/.test(l.trim())?!0:"Please enter a valid phone number in E.164 format (e.g., +12025551234)"}])).to),!n&&!i&&((await re([{type:"list",name:"contentType",message:"How would you like to provide the fax content?",choices:[{name:"File",value:"file"},{name:"URL",value:"url"}]}])).contentType==="file"?n=await So():i=(await re([{type:"input",name:"contentUrl",message:"Enter the URL of the content to send:",validate:p=>{if(!p||p.trim().length===0)return"Content URL is required";try{return new URL(p),!0}catch{return"Please enter a valid URL (e.g., https://example.com/document.pdf)"}}}])).contentUrl));let o=await Ie();s.json||(t.newline(),c.start("Sending fax..."));let r=await o.sendFax({to:e,from:s.from,file:n,contentUrl:i,serviceId:s.serviceId});s.json?console.log(JSON.stringify(r,null,2)):(c.succeed("Fax sent successfully!"),t.newline(),t.info("Fax Details:"),t.info(`ID: ${r.id}`),t.info(`To: ${r.to}`),t.info(`From: ${r.from}`),t.info(`Status: ${r.status}`),t.info(`Service ID: ${r.serviceId}`),t.info(`Created: ${r.createTime}`),t.newline(),t.info('\u{1F4A1} Tip: Use "sinch fax get <fax-id>" to check fax status'),t.newline())}catch(e){s.json?console.error(JSON.stringify({error:e.message},null,2)):(c.fail("Failed to send fax"),t.error(e.message)),process.exit(1)}});Oe.command("list").description("List sent faxes").option("-l, --limit <number>","Maximum number of faxes to return","10").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async s=>{try{await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline()}catch(e){t.error(`Failed to list faxes: ${e.message}`),process.exit(1)}});Oe.command("get").description("Get fax details").argument("<fax-id>","Fax ID").option("--service-id <id>","Fax service ID (uses default if not specified)").option("--json","Output result as JSON").action(async(s,e)=>{try{await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline()}catch(n){t.error(`Failed to get fax: ${n.message}`),process.exit(1)}});Oe.command("cancel").description("Cancel a pending fax").argument("<fax-id>","Fax ID to cancel").option("--service-id <id>","Fax service ID (uses default if not specified)").action(async(s,e)=>{try{await Ie(),t.newline(),t.info("\u{1F4E0} Coming soon!"),t.newline()}catch(n){t.error(`Failed to cancel fax: ${n.message}`),process.exit(1)}});Oe.command("status").description("Check fax service authentication status").action(async()=>{try{await u.load();let s=await u.hasFaxCredentials(),e=u.getFaxPublicCredentialInfo(),n=u.getFaxServiceId(),i=u.getFaxSenderNumber();t.newline(),s?(t.info("\u2713 Fax service authenticated"),t.info(`Project ID: ${e.projectId||"N/A"}`),t.info(`Key ID: ${e.keyId||"N/A"}`),t.info(`Service ID: ${n||"Not configured"}`),t.info(`Sender Number: ${i||"Not configured"}`),t.info(`Source: ${e.source}`)):(t.info("\u2717 Not authenticated"),t.info("Run: sinch auth login")),t.newline()}catch(s){t.error(`Failed to check status: ${s.message}`),process.exit(1)}});ia=Oe});var Mn=require("commander"),m=h(require("chalk")),Te=h(require("fs-extra")),Ht=h(require("path")),Jn=h(require("os")),ko=require("child_process");var _e=h(require("fs")),Wt=h(require("path")),Gt=h(require("chalk")),No=18e5,Oo="https://registry.npmjs.org/@sinch/cli";function To(){if(process.platform!=="win32")try{if(_e.default.existsSync("/.dockerenv"))return!0;let s=_e.default.readFileSync("/proc/1/cgroup","utf8");return s.includes("docker")||s.includes("containerd")}catch{return!1}return!!process.env.DOCKER_CONTAINER}function Fo(){return!!process.env.CI}function Lo(){return To()||Fo()}function _o(s){return s.includes("-dev.")?"dev":parseInt(s.split(".")[0]||"0")>=1?"latest":"beta"}function Uo(s){try{if(!_e.default.existsSync(s))return!0;let e=parseInt(_e.default.readFileSync(s,"utf8"));return Date.now()-e>No}catch{return!0}}function qo(s,e){let n=s.replace(/^v/,"").split("-")[0]||"0.0.0",i=e.replace(/^v/,"").split("-")[0]||"0.0.0",o=n.split(".").map(a=>parseInt(a)||0),r=i.split(".").map(a=>parseInt(a)||0);for(let a=0;a<3;a++){let l=o[a]||0,p=r[a]||0;if(p>l)return!0;if(p<l)return!1}if(s.includes("-dev.")&&e.includes("-dev.")){let a=parseInt(s.split("-dev.")[1]||"0");return parseInt(e.split("-dev.")[1]||"0")>a}return!1}async function Mo(s){try{let e=await fetch(Oo,{signal:AbortSignal.timeout(3e3)});return e.ok&&(await e.json())["dist-tags"]?.[s]||null}catch{return null}}async function Jo(s,e){let n=zt().version,i=_o(n);try{let o=await Mo(i);if(!o)return;qo(n,o)&&(console.log(Gt.default.yellow(`
151
151
  \u{1F4E6} Update available: ${n} \u2192 ${o}`)),console.log(Gt.default.cyan(`Run: npm install -g @sinch/cli@${i}
152
- `))),_e.default.mkdirSync(s,{recursive:!0}),_e.default.writeFileSync(e,Date.now().toString())}catch{}}function Hn(){if(Fo())return;let s=Wt.default.join(require("os").homedir(),".sinch"),e=Wt.default.join(s,".last-update-check");_o(e)&&Mo(s,e).catch(()=>{})}process.env.NODE_NO_WARNINGS||(process.env.NODE_NO_WARNINGS="1",process.removeAllListeners("warning"));Hn();var ia=zt(),sa=os(),oa=cs(),ra=us(),aa=ms(),ca=Ss(),la=Ks(),da=uo(),pa=($o(),M(vo)),Z=new Mn.Command;Z.name("sinch").description("Sinch Functions - Serverless function platform for voice applications").version(ia.version,"-V, --version","output the version number").helpOption("-h, --help","Display help for command");Z.addCommand(sa);Z.addCommand(oa);Z.addCommand(ra);Z.addCommand(aa);Z.addCommand(ca);Z.addCommand(la);Z.addCommand(da);Z.addCommand(pa);var jt=new Mn.Command("auth");jt.description("Authentication management for Sinch Voice API");jt.command("login").description("Authenticate with Sinch Voice API").option("-f, --credentials-file <path>","Path to credentials JSON file").action(async s=>{let{config:e}=(k(),M(qe)),n=require("inquirer");try{if(await e.load(),s.credentialsFile){console.log(m.default.blue(`
152
+ `))),_e.default.mkdirSync(s,{recursive:!0}),_e.default.writeFileSync(e,Date.now().toString())}catch{}}function Hn(){if(Lo())return;let s=Wt.default.join(require("os").homedir(),".sinch"),e=Wt.default.join(s,".last-update-check");Uo(e)&&Jo(s,e).catch(()=>{})}process.env.NODE_NO_WARNINGS||(process.env.NODE_NO_WARNINGS="1",process.removeAllListeners("warning"));Hn();var sa=zt(),oa=os(),ra=cs(),aa=us(),ca=ms(),la=Ss(),da=Ks(),pa=uo(),Io=($o(),M(vo)),ua=Io.default||Io,Z=new Mn.Command;Z.name("sinch").description("Sinch Functions - Serverless function platform for voice applications").version(sa.version,"-V, --version","output the version number").helpOption("-h, --help","Display help for command");Z.addCommand(oa);Z.addCommand(ra);Z.addCommand(aa);Z.addCommand(ca);Z.addCommand(la);Z.addCommand(da);Z.addCommand(pa);Z.addCommand(ua);var jt=new Mn.Command("auth");jt.description("Authentication management for Sinch Voice API");jt.command("login").description("Authenticate with Sinch Voice API").option("-f, --credentials-file <path>","Path to credentials JSON file").action(async s=>{let{config:e}=(k(),M(qe)),n=require("inquirer");try{if(await e.load(),s.credentialsFile){console.log(m.default.blue(`
153
153
  \u{1F510} Sinch Voice API Authentication`)),console.log(m.default.gray(`Loading credentials from: ${s.credentialsFile}
154
154
  `)),Te.default.existsSync(s.credentialsFile)||(console.error(m.default.red(`\u274C Credentials file not found: ${s.credentialsFile}`)),process.exit(1));try{let p=Te.default.readFileSync(s.credentialsFile,"utf-8"),d=JSON.parse(p),g=["projectId","keyId","keySecret","applicationKey","applicationSecret"].filter(v=>!d[v]);g.length>0&&(console.error(m.default.red(`\u274C Missing required fields in credentials file: ${g.join(", ")}`)),console.error(m.default.gray(`
155
155
  Expected format:`)),console.error(m.default.gray(JSON.stringify({projectId:"your-project-id",keyId:"your-key-id",keySecret:"your-key-secret",applicationKey:"your-app-key",applicationSecret:"your-app-secret"},null,2))),process.exit(1));let w={projectId:d.projectId,keyId:d.keyId,keySecret:d.keySecret,applicationKey:d.applicationKey,applicationSecret:d.applicationSecret},{spinner:y}=(E(),M(et));y.start("Verifying credentials...");try{y.update("Obtaining OAuth access token...");let{SinchAPI:v}=(z(),M(Xe)),P=await new v({apiUrl:e.get("apiUrl"),projectId:w.projectId,credentials:e._credentials}).authenticateOAuth(w.keyId,w.keySecret);y.succeed("OAuth token obtained successfully!"),y.start("Testing Voice API connection...");let{SinchClient:D}=require("@sinch/sdk-core");await new D({applicationKey:w.applicationKey,applicationSecret:w.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:w.applicationKey}),y.succeed("Credentials verified successfully!"),await e._credentials.storeOAuthToken(P),await e._credentials.store(w),console.log(m.default.green(`
@@ -168,16 +168,16 @@ Expected format:`)),console.error(m.default.gray(JSON.stringify({projectId:"your
168
168
  Fax configuration:`)),console.log(m.default.gray(" sinch config --set fax serviceID=<id>")),console.log(m.default.gray(" sinch config --set fax senderNumber=<number>")),console.log(m.default.gray(' sinch config --get "fax serviceID"')),console.log(m.default.gray(` sinch config --get "fax senderNumber"
169
169
  `))}catch(n){console.error(m.default.red(`Failed to manage config: ${n.message}`)),process.exit(1)}});Z.command("health").description("Check API connection and health").action(async()=>{let{SinchAPI:s}=(z(),M(Xe)),{config:e}=(k(),M(qe)),{spinner:n}=(E(),M(et));try{await e.load();let i=new s(e.getApiConfig());n.start("Checking API health...");let o=await i.checkHealth();n.succeed("API is healthy"),console.log(m.default.blue(`
170
170
  \u{1F3E5} Health Status:`)),console.log(` Status: ${m.default.green(o.status)}`),console.log(` API URL: ${e.get("apiUrl")}`),console.log(` Project ID: ${e.get("projectId")}`)}catch(i){n.fail("API health check failed"),console.error(m.default.red(`
171
- \u274C ${i.message}`)),process.exit(1)}});Z.command("completion").description("Generate shell completion scripts").option("--shell <shell>","Shell type (powershell, bash, zsh)","powershell").option("--install","Automatically install completion (PowerShell only)").action(async s=>{let e=s.shell.toLowerCase();s.install&&e==="powershell"?await fa():e==="powershell"?ha():e==="bash"?ya():e==="zsh"?wa():(console.error(m.default.red(`Unsupported shell: ${e}`)),console.log("Supported shells: powershell, bash, zsh"),process.exit(1))});process.on("uncaughtException",s=>{console.error(m.default.red(`
171
+ \u274C ${i.message}`)),process.exit(1)}});Z.command("completion").description("Generate shell completion scripts").option("--shell <shell>","Shell type (powershell, bash, zsh)","powershell").option("--install","Automatically install completion (PowerShell only)").action(async s=>{let e=s.shell.toLowerCase();s.install&&e==="powershell"?await ga():e==="powershell"?ya():e==="bash"?wa():e==="zsh"?Ca():(console.error(m.default.red(`Unsupported shell: ${e}`)),console.log("Supported shells: powershell, bash, zsh"),process.exit(1))});process.on("uncaughtException",s=>{console.error(m.default.red(`
172
172
  \u{1F4A5} Uncaught Exception: ${s.message}`)),process.env.DEBUG&&console.error(s.stack),process.exit(1)});process.on("unhandledRejection",s=>{console.error(m.default.red(`
173
- \u{1F4A5} Unhandled Rejection: ${s}`)),process.env.DEBUG&&console.error(s),process.exit(1)});async function ua(){let s=process.argv.slice(2),e=s[0],n=["auth","config","help","completion","--help","-h","--version","-V"],i=s.includes("--non-interactive");if(e&&!n.includes(e)&&!n.some(o=>s.includes(o))){let{config:o}=(k(),M(qe));await o.load();let r=e==="fax",a=!1,l="Sinch",p="sinch auth login";if(a=await o.hasCredentials(),r&&(l="Sinch Fax API"),!a){i&&(console.error(m.default.red(`
173
+ \u{1F4A5} Unhandled Rejection: ${s}`)),process.env.DEBUG&&console.error(s),process.exit(1)});async function fa(){let s=process.argv.slice(2),e=s[0],n=["auth","config","help","completion","--help","-h","--version","-V"],i=s.includes("--non-interactive");if(e&&!n.includes(e)&&!n.some(o=>s.includes(o))){let{config:o}=(k(),M(qe));await o.load();let r=e==="fax",a=!1,l="Sinch",p="sinch auth login";if(a=await o.hasCredentials(),r&&(l="Sinch Fax API"),!a){i&&(console.error(m.default.red(`
174
174
  \u274C Authentication required`)),console.error(`Please set up authentication first with: ${p}`),console.error("Or provide credentials via environment variables for CI/CD"),process.exit(1));let d=require("inquirer");console.log(m.default.yellow(`
175
175
  \u26A0\uFE0F Authentication Required`)),console.log(`You need to authenticate with ${l} to use the CLI.
176
176
  `);let{shouldLogin:f}=await d.prompt([{type:"confirm",name:"shouldLogin",message:"Would you like to login now?",default:!0}]);f?process.argv.splice(2,process.argv.length-2,"auth","login"):(console.log(`
177
177
  You can authenticate anytime with:`),console.log(` ${m.default.cyan(p)}
178
178
  `),process.exit(0))}}Z.parse(process.argv),process.argv.slice(2).length||(console.log(m.default.blue.bold(`
179
179
  \u{1F3AF} Sinch Functions CLI`)),console.log(m.default.gray(`Serverless function platform for voice applications
180
- `)),console.log("Quick start:"),console.log(` ${m.default.cyan("sinch auth login")} # Authenticate with Sinch Voice API`),console.log(` ${m.default.cyan("sinch templates list")} # Browse available templates`),console.log(` ${m.default.cyan("sinch functions init")} # Create a new function`),console.log(` ${m.default.cyan("sinch functions dev")} # Start local development`),console.log(` ${m.default.cyan("sinch voice callback-url")} # Update webhook URL for live testing`),console.log(` ${m.default.cyan("sinch functions deploy")} # Deploy to production`),console.log(` ${m.default.cyan("sinch functions status [id]")} # Check deployment status`),console.log(` ${m.default.cyan("sinch secrets list")} # Manage custom secrets`),console.log(""),Z.help())}ua().catch(s=>{console.error(m.default.red("Error:"),s.message),process.exit(1)});async function fa(){let{spinner:s}=(E(),M(et));try{s.start("Installing PowerShell completion...");let e=Ht.default.join(Jn.default.homedir(),"Documents","PowerShell"),n=Ht.default.join(e,"sinch-completion.ps1");await Te.default.ensureDir(e),s.update("Creating completion script...");let i=ma();await Te.default.writeFile(n,i),s.update("Updating PowerShell profile...");let o=await ga(),r="";await Te.default.pathExists(o)&&(r=await Te.default.readFile(o,"utf8"));let a='. "$env:USERPROFILE\\Documents\\PowerShell\\sinch-completion.ps1"';if(r.includes("sinch-completion.ps1"))s.info("PowerShell completion already installed"),console.log(m.default.blue(`
180
+ `)),console.log("Quick start:"),console.log(` ${m.default.cyan("sinch auth login")} # Authenticate with Sinch Voice API`),console.log(` ${m.default.cyan("sinch templates list")} # Browse available templates`),console.log(` ${m.default.cyan("sinch functions init")} # Create a new function`),console.log(` ${m.default.cyan("sinch functions dev")} # Start local development`),console.log(` ${m.default.cyan("sinch voice callback-url")} # Update webhook URL for live testing`),console.log(` ${m.default.cyan("sinch functions deploy")} # Deploy to production`),console.log(` ${m.default.cyan("sinch functions status [id]")} # Check deployment status`),console.log(` ${m.default.cyan("sinch secrets list")} # Manage custom secrets`),console.log(""),Z.help())}fa().catch(s=>{console.error(m.default.red("Error:"),s.message),process.exit(1)});async function ga(){let{spinner:s}=(E(),M(et));try{s.start("Installing PowerShell completion...");let e=Ht.default.join(Jn.default.homedir(),"Documents","PowerShell"),n=Ht.default.join(e,"sinch-completion.ps1");await Te.default.ensureDir(e),s.update("Creating completion script...");let i=ha();await Te.default.writeFile(n,i),s.update("Updating PowerShell profile...");let o=await ma(),r="";await Te.default.pathExists(o)&&(r=await Te.default.readFile(o,"utf8"));let a='. "$env:USERPROFILE\\Documents\\PowerShell\\sinch-completion.ps1"';if(r.includes("sinch-completion.ps1"))s.info("PowerShell completion already installed"),console.log(m.default.blue(`
181
181
  \u2139\uFE0F Completion is already installed`)),console.log(m.default.gray("If tab completion isn't working, try restarting PowerShell"));else{let l=r+(r?`
182
182
  `:"")+`# Sinch Functions CLI completion
183
183
  `+a+`
@@ -185,7 +185,7 @@ You can authenticate anytime with:`),console.log(` ${m.default.cyan(p)}
185
185
  \u2705 Installation Complete!`)),console.log(m.default.blue("\u{1F4C1} Files created:")),console.log(` ${m.default.gray(n)}`),console.log(` ${m.default.gray("Updated:")} ${o}`),console.log(m.default.yellow(`
186
186
  \u26A1 To activate completion:`)),console.log(" 1. Restart PowerShell, OR"),console.log(" 2. Run: "+m.default.cyan(". $PROFILE")),console.log(m.default.gray(`
187
187
  \u{1F4A1} Test with: sinch functions <TAB>`))}}catch(e){s.fail("Failed to install PowerShell completion"),console.error(m.default.red(`\u274C Error: ${e.message}`)),console.log(m.default.yellow(`
188
- \u{1F4A1} Try manual installation with: sinch completion`)),process.exit(1)}}async function ga(){return new Promise(s=>{let e=n=>new Promise(i=>{let o=(0,Io.spawn)(n,["-Command","$PROFILE"],{stdio:["ignore","pipe","pipe"]}),r="";o.stdout.on("data",a=>{r+=a.toString()}),o.on("close",a=>{i(a===0?{success:!0,path:r.trim(),version:n}:{success:!1})}),o.on("error",()=>{i({success:!1})})});e("pwsh").then(n=>{n.success&&n.path?(console.log(m.default.gray(` Detected PowerShell 7 profile: ${n.path}`)),s(n.path)):e("powershell").then(i=>{if(i.success&&i.path)console.log(m.default.gray(` Detected Windows PowerShell profile: ${i.path}`)),s(i.path);else{let o=Ht.default.join(Jn.default.homedir(),"Documents","PowerShell","Microsoft.PowerShell_profile.ps1");console.log(m.default.gray(` Using fallback profile path: ${o}`)),s(o)}})})})}function ma(){return`# PowerShell completion for Sinch Functions CLI
188
+ \u{1F4A1} Try manual installation with: sinch completion`)),process.exit(1)}}async function ma(){return new Promise(s=>{let e=n=>new Promise(i=>{let o=(0,ko.spawn)(n,["-Command","$PROFILE"],{stdio:["ignore","pipe","pipe"]}),r="";o.stdout.on("data",a=>{r+=a.toString()}),o.on("close",a=>{i(a===0?{success:!0,path:r.trim(),version:n}:{success:!1})}),o.on("error",()=>{i({success:!1})})});e("pwsh").then(n=>{n.success&&n.path?(console.log(m.default.gray(` Detected PowerShell 7 profile: ${n.path}`)),s(n.path)):e("powershell").then(i=>{if(i.success&&i.path)console.log(m.default.gray(` Detected Windows PowerShell profile: ${i.path}`)),s(i.path);else{let o=Ht.default.join(Jn.default.homedir(),"Documents","PowerShell","Microsoft.PowerShell_profile.ps1");console.log(m.default.gray(` Using fallback profile path: ${o}`)),s(o)}})})})}function ha(){return`# PowerShell completion for Sinch Functions CLI
189
189
  # Auto-generated by 'sinch completion --install'
190
190
  # Compatible with both PowerShell 7 and Windows PowerShell 5.1
191
191
 
@@ -232,7 +232,7 @@ Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
232
232
  # Silently fail if there are any errors in completion
233
233
  # This prevents PowerShell startup errors
234
234
  }
235
- }`}function ha(){let s=`
235
+ }`}function ya(){let s=`
236
236
  # PowerShell completion for Sinch Functions CLI
237
237
  Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
238
238
  param($wordToComplete, $commandAst, $cursorPosition)
@@ -283,7 +283,7 @@ Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
283
283
  #
284
284
  # To find your profile location, run: $PROFILE
285
285
  `;console.log(m.default.blue("\u{1F527} PowerShell Completion Script")),console.log(m.default.gray(`Copy and save this to your PowerShell profile:
286
- `)),console.log(s),console.log(m.default.yellow("Installation Instructions:")),console.log(m.default.green("\u{1F680} Easy way: ")+m.default.cyan("sinch completion --install")),console.log(m.default.gray("\u{1F4DD} Manual way:")),console.log("1. Save this script as sinch-completion.ps1 in your Documents\\PowerShell folder"),console.log("2. Add this line to your PowerShell profile:"),console.log(m.default.cyan(' . "$env:USERPROFILE\\\\Documents\\\\PowerShell\\\\sinch-completion.ps1"')),console.log("3. Restart PowerShell or run: . $PROFILE")}function ya(){let s=`
286
+ `)),console.log(s),console.log(m.default.yellow("Installation Instructions:")),console.log(m.default.green("\u{1F680} Easy way: ")+m.default.cyan("sinch completion --install")),console.log(m.default.gray("\u{1F4DD} Manual way:")),console.log("1. Save this script as sinch-completion.ps1 in your Documents\\PowerShell folder"),console.log("2. Add this line to your PowerShell profile:"),console.log(m.default.cyan(' . "$env:USERPROFILE\\\\Documents\\\\PowerShell\\\\sinch-completion.ps1"')),console.log("3. Restart PowerShell or run: . $PROFILE")}function wa(){let s=`
287
287
  # Bash completion for Sinch Functions CLI
288
288
  _sinch_completion() {
289
289
  local cur prev commands
@@ -324,7 +324,7 @@ complete -F _sinch_completion sinch
324
324
 
325
325
  # To install: Add this to your ~/.bashrc or ~/.bash_profile
326
326
  `;console.log(m.default.blue("\u{1F527} Bash Completion Script")),console.log(m.default.gray(`Add this to your ~/.bashrc or ~/.bash_profile:
327
- `)),console.log(s)}function wa(){let s=`
327
+ `)),console.log(s)}function Ca(){let s=`
328
328
  #compdef sinch
329
329
 
330
330
  _sinch() {