@sinch/cli 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +45 -48
  2. package/package.json +4 -1
package/dist/index.js CHANGED
@@ -1,22 +1,22 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Hn=Object.create;var Ke=Object.defineProperty;var Gn=Object.getOwnPropertyDescriptor;var Yn=Object.getOwnPropertyNames;var zn=Object.getPrototypeOf,Qn=Object.prototype.hasOwnProperty;var fe=(o,e)=>()=>(o&&(e=o(o=0)),e);var N=(o,e)=>()=>(e||o((e={exports:{}}).exports,e),e.exports),Be=(o,e)=>{for(var n in e)Ke(o,n,{get:e[n],enumerable:!0})},St=(o,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Yn(e))!Qn.call(o,r)&&r!==n&&Ke(o,r,{get:()=>e[r],enumerable:!(i=Gn(e,r))||i.enumerable});return o};var m=(o,e,n)=>(n=o!=null?Hn(zn(o)):{},St(e||!o||!o.__esModule?Ke(n,"default",{value:o,enumerable:!0}):n,o)),O=o=>St(Ke({},"__esModule",{value:!0}),o);var Qe=N((yi,Zn)=>{Zn.exports={name:"@sinch/cli",version:"0.1.9",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",prepublishOnly:"npm run build:prod"},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:{"@sinch/sdk-core":"^1.2.1","adm-zip":"^0.5.10",axios:"^1.7.9",blessed:"^0.1.81",chalk:"^4.1.2",chokidar:"^3.6.0","cli-spinners":"^2.9.2","cli-table3":"^0.6.3",clipboardy:"^2.3.0",commander:"^12.1.0",eventsource:"^4.0.0","form-data":"^4.0.0","fs-extra":"^11.1.1",inquirer:"8.2.6",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/keytar":"^4.4.0","@types/node":"^24.3.0",jest:"^29.7.0",nodemon:"^3.0.1",tsup:"^8.5.0",tsx:"^4.20.4",typescript:"^5.9.2"},engines:{node:">=20.0.0",npm:">=9.0.0"}}});var De={};Be(De,{SinchAPI:()=>A});var Ve,Xe,ke,A,L=fe(()=>{"use strict";Ve=m(require("axios")),Xe=m(require("form-data")),ke=m(require("chalk")),A=class{baseUrl;projectId;timeout;credentials;client;constructor(e={}){this.baseUrl=e.apiUrl||"https://functions.api.sinch.com/",this.projectId=e.projectId||"",this.timeout=e.timeout||3e4,this.credentials=e.credentials||null,this.client=Ve.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}`)}return process.env.DEBUG_HTTP&&console.log(ke.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(ke.default.gray(`\u2190 ${n.status} ${n.config.url}`)),n),async n=>{if(process.env.DEBUG_HTTP&&console.log(ke.default.red(`\u2190 ${n.response?.status||"ERROR"} ${n.config?.url}`)),n.response?.status===401&&this.credentials&&n.config){let i=n.config;if(!i._retry){i._retry=!0;try{let r=await this.getValidToken();if(r)return i.headers.Authorization=`${r.token_type} ${r.access_token}`,this.client.request(i)}catch{console.error(ke.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,r){try{let s=new Xe.default;return s.append("name",e),s.append("runtime",n),s.append("code",i,{filename:"function.zip"}),r&&s.append("configuration",JSON.stringify(r)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,s,{headers:{...s.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(s){throw this._handleError(s,"Failed to deploy function")}}async updateFunction(e,n,i){try{let r=new Xe.default;return r.append("code",n,{filename:"function.zip"}),i&&r.append("configuration",JSON.stringify(i)),(await this.client.put(`/v1/projects/${this.projectId}/functions/${e}`,r,{headers:{...r.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(r){throw this._handleError(r,`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(r){throw this._handleError(r,"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 r=l=>l.status?"status":l.progress?"progress":l.completed?"completed":l.failed||l.error?"failed":l.connected?"connected":"message",s=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 l=await this.credentials.retrieve();if(l&&l.keyId&&l.keySecret){let u=Buffer.from(`${l.keyId}:${l.keySecret}`).toString("base64");a.Authorization=`Basic ${u}`}}catch(l){console.error("Failed to add authentication:",l)}let c=null;try{c=new AbortController;let l=await fetch(s,{method:"GET",headers:a,signal:c.signal});if(!l.ok)throw new Error(`SSE connection failed: ${l.status} ${l.statusText}`);if(!l.body)throw new Error("Response body is null");let u=l.body.getReader(),g=new TextDecoder,h="";return(async()=>{let w="";try{for(;;){let{done:T,value:q}=await u.read();if(T)break;let $=g.decode(q,{stream:!0});h+=$;let C=h.split(`
3
- `);h=C.pop()||"";for(let b of C){if(b.startsWith("event:")){w=b.substring(6).trim();continue}if(b.startsWith("data:")){let y=b.substring(5).trim();if(y)try{let P=JSON.parse(y),Q=w||r(P);n({type:Q,data:P}),w=""}catch{n({type:w||"message",data:y}),w=""}}b===""&&(w="")}}}catch(T){T.name!=="AbortError"&&i&&i(T)}})(),()=>{c&&c.abort()}}catch(l){throw console.error("Failed to create SSE stream:",l),i&&i(l),l}}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(ke.default.yellow("Failed to get authentication token:",e.message)),null}}async authenticateOAuth(e,n){try{let i="https://auth.sinch.com/oauth2/token",r=new URLSearchParams;r.append("grant_type","client_credentials");let a=(await Ve.default.post(i,r,{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(Ve.default.isAxiosError(e)){let i=e;if(i.response){let r=i.response.status,s=i.response.data,a=s?.message||s?.error||i.message;throw r===401?new Error('Authentication required. Please run "sinch auth login" first.'):r===403?new Error(`Permission denied: ${a}`):r===404?new Error(`Resource not found: ${a}`):r>=500?new Error(`Server error: ${a}`):new Error(`${n}: ${a}`)}else throw i.request?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`):new Error(`${n}: ${i.message}`)}else throw new Error(`${n}: ${e.message||e}`)}}});function qe(){if(!et)try{et=require("keytar")}catch{return null}return et}var kt,Z,et,je,U,Me,Pt=fe(()=>{"use strict";kt=m(require("os")),Z=m(require("chalk")),et=null;je="sinch-functions-cli",U=kt.userInfo().username,Me=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=qe();if(!e)return this.keychainAvailable=!1,!1;let n=`${U}-test-${Date.now()}`;return await e.setPassword(je,n,"test"),await e.deletePassword(je,n),this.keychainAvailable=!0,!0}catch{return this.keychainAvailable=!1,!1}}async setPassword(e,n){if(!await this.isKeychainAvailable())return!1;let r=qe();return r?(await r.setPassword(je,e,n),!0):!1}async getPassword(e){if(!await this.isKeychainAvailable())return null;let i=qe();return i?await i.getPassword(je,e):null}async deletePassword(e){if(!await this.isKeychainAvailable())return!1;try{let i=qe();return i?(await i.deletePassword(je,e),!0):!1}catch{return!0}}async store(e){let{projectId:n,keyId:i,keySecret:r,applicationKey:s,applicationSecret:a}=e,c=await this.setPassword(`${U}-keySecret`,r),l=await this.setPassword(s,a);c&&l?(this.config.set("keySecretPlaintext",null),this.config.set("applicationSecretPlaintext",null)):(console.log(Z.default.yellow(`
2
+ "use strict";var Mn=Object.create;var Ne=Object.defineProperty;var Wn=Object.getOwnPropertyDescriptor;var Hn=Object.getOwnPropertyNames;var Gn=Object.getPrototypeOf,Yn=Object.prototype.hasOwnProperty;var de=(o,e)=>()=>(o&&(e=o(o=0)),e);var N=(o,e)=>()=>(e||o((e={exports:{}}).exports,e),e.exports),Ue=(o,e)=>{for(var n in e)Ne(o,n,{get:e[n],enumerable:!0})},bt=(o,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Hn(e))!Yn.call(o,r)&&r!==n&&Ne(o,r,{get:()=>e[r],enumerable:!(i=Wn(e,r))||i.enumerable});return o};var m=(o,e,n)=>(n=o!=null?Mn(Gn(o)):{},bt(e||!o||!o.__esModule?Ne(n,"default",{value:o,enumerable:!0}):n,o)),D=o=>bt(Ne({},"__esModule",{value:!0}),o);var Ge=N((mi,zn)=>{zn.exports={name:"@sinch/cli",version:"0.1.10",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","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"},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:{"@sinch/sdk-core":"^1.2.1","adm-zip":"^0.5.10",axios:"^1.7.9",blessed:"^0.1.81",chalk:"^4.1.2",chokidar:"^3.6.0","cli-spinners":"^2.9.2","cli-table3":"^0.6.3",clipboardy:"^2.3.0",commander:"^12.1.0",eventsource:"^4.0.0","form-data":"^4.0.0","fs-extra":"^11.1.1",inquirer:"8.2.6",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/keytar":"^4.4.0","@types/node":"^24.3.0",execa:"^5.1.1",jest:"^29.7.0",nodemon:"^3.0.1",tsup:"^8.5.0",tsx:"^4.20.4",typescript:"^5.9.2"},engines:{node:">=20.0.0",npm:">=9.0.0"}}});var $e={};Ue($e,{SinchAPI:()=>E});var Be,Qe,ve,E,_=de(()=>{"use strict";Be=m(require("axios")),Qe=m(require("form-data")),ve=m(require("chalk")),E=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=Be.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}`)}return process.env.DEBUG_HTTP&&console.log(ve.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(ve.default.gray(`\u2190 ${n.status} ${n.config.url}`)),n),async n=>{if(process.env.DEBUG_HTTP&&console.log(ve.default.red(`\u2190 ${n.response?.status||"ERROR"} ${n.config?.url}`)),n.response?.status===401&&this.credentials&&n.config){let i=n.config;if(!i._retry){i._retry=!0;try{let r=await this.getValidToken();if(r)return i.headers.Authorization=`${r.token_type} ${r.access_token}`,this.client.request(i)}catch{console.error(ve.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,r){try{let s=new Qe.default;return s.append("name",e),s.append("runtime",n),s.append("code",i,{filename:"function.zip"}),r&&s.append("configuration",JSON.stringify(r)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,s,{headers:{...s.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(s){throw this._handleError(s,"Failed to deploy function")}}async updateFunction(e,n,i){try{let r=new Qe.default;return r.append("code",n,{filename:"function.zip"}),i&&r.append("configuration",JSON.stringify(i)),(await this.client.put(`/v1/projects/${this.projectId}/functions/${e}`,r,{headers:{...r.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(r){throw this._handleError(r,`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(r){throw this._handleError(r,"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 r=l=>l.status?"status":l.progress?"progress":l.completed?"completed":l.failed||l.error?"failed":l.connected?"connected":"message",s=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 l=await this.credentials.retrieve();if(l&&l.keyId&&l.keySecret){let u=Buffer.from(`${l.keyId}:${l.keySecret}`).toString("base64");a.Authorization=`Basic ${u}`}}catch(l){console.error("Failed to add authentication:",l)}let c=null;try{c=new AbortController;let l=await fetch(s,{method:"GET",headers:a,signal:c.signal});if(!l.ok)throw new Error(`SSE connection failed: ${l.status} ${l.statusText}`);if(!l.body)throw new Error("Response body is null");let u=l.body.getReader(),g=new TextDecoder,h="";return(async()=>{let w="";try{for(;;){let{done:T,value:V}=await u.read();if(T)break;let $=g.decode(V,{stream:!0});h+=$;let b=h.split(`
3
+ `);h=b.pop()||"";for(let C of b){if(C.startsWith("event:")){w=C.substring(6).trim();continue}if(C.startsWith("data:")){let y=C.substring(5).trim();if(y)try{let P=JSON.parse(y),Q=w||r(P);n({type:Q,data:P}),w=""}catch{n({type:w||"message",data:y}),w=""}}C===""&&(w="")}}}catch(T){T.name!=="AbortError"&&i&&i(T)}})(),()=>{c&&c.abort()}}catch(l){throw console.error("Failed to create SSE stream:",l),i&&i(l),l}}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(ve.default.yellow("Failed to get authentication token:",e.message)),null}}async authenticateOAuth(e,n){try{let i=this.oauthUrl,r=new URLSearchParams;r.append("grant_type","client_credentials");let a=(await Be.default.post(i,r,{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(Be.default.isAxiosError(e)){let i=e;if(i.response){let r=i.response.status,s=i.response.data,a=s?.message||s?.error||i.message;throw r===401?new Error('Authentication required. Please run "sinch auth login" first.'):r===403?new Error(`Permission denied: ${a}`):r===404?new Error(`Resource not found: ${a}`):r>=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 Ke(){if(!Ze)try{Ze=require("keytar")}catch{return null}return Ze}var vt,Z,Ze,Re,U,qe,$t=de(()=>{"use strict";vt=m(require("os")),Z=m(require("chalk")),Ze=null;Re="sinch-functions-cli",U=vt.userInfo().username,qe=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=Ke();if(!e)return this.keychainAvailable=!1,!1;let n=`${U}-test-${Date.now()}`;return await e.setPassword(Re,n,"test"),await e.deletePassword(Re,n),this.keychainAvailable=!0,!0}catch{return this.keychainAvailable=!1,!1}}async setPassword(e,n){if(!await this.isKeychainAvailable())return!1;let r=Ke();return r?(await r.setPassword(Re,e,n),!0):!1}async getPassword(e){if(!await this.isKeychainAvailable())return null;let i=Ke();return i?await i.getPassword(Re,e):null}async deletePassword(e){if(!await this.isKeychainAvailable())return!1;try{let i=Ke();return i?(await i.deletePassword(Re,e),!0):!1}catch{return!0}}async store(e){let{projectId:n,keyId:i,keySecret:r,applicationKey:s,applicationSecret:a}=e,c=await this.setPassword(`${U}-keySecret`,r),l=await this.setPassword(s,a);c&&l?(this.config.set("keySecretPlaintext",null),this.config.set("applicationSecretPlaintext",null)):(console.log(Z.default.yellow(`
4
4
  \u26A0\uFE0F OS keychain not available (Docker/CI environment detected)`)),console.log(Z.default.yellow("\u26A0\uFE0F Storing secrets in plaintext config file")),console.log(Z.default.gray("Location: ~/.sinch/config.json")),console.log(Z.default.gray(`
5
- For better security, export as environment variables instead:`)),console.log(Z.default.cyan(' export SINCH_KEY_SECRET="'+r+'"')),console.log(Z.default.cyan(' export SINCH_APPLICATION_SECRET="'+a+'"')),this.config.set("keySecretPlaintext",r),this.config.set("applicationSecretPlaintext",a)),this.config.set("projectId",n),this.config.set("keyId",i),this.config.set("defaultApplicationKey",s),this.config.set("credentialsStored",!0),await this.config.save()}async storeOAuthToken(e){let{access_token:n,refresh_token:i,expires_in:r,token_type:s}=e,a=new Date(Date.now()+r*1e3).toISOString(),c=await this.setPassword(`${U}-oauth-access`,n),l=!0;i&&(l=await this.setPassword(`${U}-oauth-refresh`,i)),this.config.set("oauthTokenType",s),this.config.set("oauthExpiresAt",a),this.config.set("oauthStored",c&&l),await this.config.save()}async reAuthenticateOAuth(){try{let e=await this.retrieve();if(!e)return null;let{SinchAPI:n}=(L(),O(De)),r=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(r),r.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(Z.default.gray("Token expired, re-authenticating..."));let i=await this.reAuthenticateOAuth();return i?console.log(Z.default.green("\u2713 Token renewed successfully")):console.warn(Z.default.yellow("Failed to renew OAuth token. Please login again.")),i}return await this.getPassword(`${U}-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,r=process.env.SINCH_APPLICATION_SECRET;if(e&&n&&i&&r)return{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId")||"",keyId:e,keySecret:n,applicationKey:i,applicationSecret:r};if(!this.config.get("credentialsStored"))return null;let a=this.config.get("projectId"),c=this.config.get("keyId"),l=this.config.get("defaultApplicationKey"),u=await this.getPassword(`${U}-keySecret`),g=l?await this.getPassword(l):null;return(!u||!g)&&(u=u||n||null,g=g||r||null),(!u||!g)&&(u=u||this.config.get("keySecretPlaintext"),g=g||this.config.get("applicationSecretPlaintext")),!u||!g?null:{projectId:a,keyId:c,keySecret:u,applicationKey:l,applicationSecret:g}}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(`${U}-keySecret`),await this.deletePassword(`${U}-oauth-access`),await this.deletePassword(`${U}-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(`${U}-keySecret`),r=this.config.get("defaultApplicationKey"),s=r?await this.getPassword(r):null;return!!(i&&s)}async hasOAuthToken(){return this.config.get("oauthStored")?!!await this.getPassword(`${U}-oauth-access`):!1}getPublicInfo(){return{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")}}async createSinchClient(e=null){let n=await this.getApplicationCredentials(e);if(!n)throw new Error('No credentials found. Please run "sinch auth login" first.');let{SinchClient:i}=require("@sinch/sdk-core");return new i({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret,projectId:this.config.get("projectId")})}async storeBasicAuthToken(e){await this.setPassword(`${U}-basic-auth`,e)&&(this.config.set("basicAuthStored",!0),await this.config.save())}async getBasicAuthToken(){return this.config.get("basicAuthStored")?await this.getPassword(`${U}-basic-auth`):null}async clearBasicAuthToken(){await this.deletePassword(`${U}-basic-auth`),this.config.set("basicAuthStored",!1),await this.config.save()}}});var he={};Be(he,{Config:()=>Je,config:()=>p});var W,Fe,At,tt,Je,p,I=fe(()=>{"use strict";W=m(require("fs-extra")),Fe=m(require("path")),At=m(require("os")),tt=m(require("chalk"));Pt();Je=class{configDir;configFile;projectConfigFile;_config=null;_projectConfig=null;_credentials=null;constructor(){this.configDir=Fe.join(At.homedir(),".sinch"),this.configFile=Fe.join(this.configDir,"config.json"),this.projectConfigFile=Fe.join(process.cwd(),"sinch.json")}async load(){try{await W.ensureDir(this.configDir),await W.pathExists(this.configFile)?this._config=await W.readJson(this.configFile):(this._config=this._getDefaultConfig(),await this.save())}catch(e){console.warn(tt.default.yellow(`Warning: Could not load config: ${e.message}`)),this._config=this._getDefaultConfig()}this._credentials=new Me(this);try{await W.pathExists(this.projectConfigFile)&&(this._projectConfig=await W.readJson(this.projectConfigFile))}catch(e){console.warn(tt.default.yellow(`Warning: Could not load project config: ${e.message}`))}}async save(){try{await W.ensureDir(this.configDir),await W.writeJson(this.configFile,this._config,{spaces:2})}catch(e){throw new Error(`Could not save config: ${e.message}`)}}async saveProjectConfig(){try{if(this._projectConfig){let e=Fe.join(process.cwd(),"sinch.json");await W.writeJson(e,this._projectConfig,{spaces:2})}}catch(e){throw new Error(`Could not save project config: ${e.message}`)}}get(e,n=null){if(!this._config)throw new Error("Config not loaded. Call load() first.");return this._projectConfig&&this._projectConfig[e]!==void 0?this._projectConfig[e]:this._config[e]!==void 0?this._config[e]:n}set(e,n,i=!1){if(!this._config)throw new Error("Config not loaded. Call load() first.");i?(this._projectConfig||(this._projectConfig={}),this._projectConfig[e]=n):this._config[e]=n}getApiConfig(){return{apiUrl:this.get("apiUrl"),projectId:this.get("projectId"),timeout:this.get("timeout"),credentials:this._credentials}}async initProject(e,n="node",i={},r=null){let s={name:e,runtime:n,version:"1.0.0",description:`Sinch Functions project: ${e}`,created:new Date().toISOString()};return i&&Object.keys(i).length>0&&(s.variables=i),r&&(s.applicationKey=r),this._projectConfig=s,await this.saveProjectConfig(),s}isInProject(){return this._projectConfig!==null}getProjectConfig(){return this._projectConfig}_getDefaultConfig(){return{apiUrl:"https://api.functions.dev.sinchvoice.org",projectId:"default-project",timeout:0,created:new Date().toISOString(),version:"1.0.0"}}async storeCredentials(e){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.store(e)}async getCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.retrieve()}async clearCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.clear()}async hasCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.hasCredentials()}getPublicCredentialInfo(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return this._credentials.getPublicInfo()}async createSinchClient(e=null){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return!e&&this.isInProject()&&(e=this._projectConfig?.applicationKey||null),await this._credentials.createSinchClient(e)}async getApplicationCredentials(e=null){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return!e&&this.isInProject()&&(e=this._projectConfig?.applicationKey||null),await this._credentials.getApplicationCredentials(e)}async storeApplicationSecret(e,n){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.storeApplicationSecret(e,n)}getTunnelPreference(){return this._projectConfig&&this._projectConfig.tunnel?.preference||null}async setTunnelPreference(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.preference=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}getTunnelSubdomain(){return this._projectConfig&&this._projectConfig.tunnel?.subdomain||null}async setTunnelSubdomain(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.subdomain=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}getTunnelUrl(){return this._projectConfig&&this._projectConfig.tunnel?.lastUrl||null}async setTunnelUrl(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.lastUrl=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}},p=new Je});var H,re,nt,Et,ot,t,K=fe(()=>{"use strict";H=m(require("chalk")),re=m(require("fs")),nt=m(require("path")),Et=m(require("os")),ot=class{verbose;logFile;constructor(e={}){this.verbose=e.verbose||process.env.VERBOSE==="true";let n="cli";try{let i=nt.join(process.cwd(),"sinch.json");re.existsSync(i)&&(n=JSON.parse(re.readFileSync(i,"utf8")).name||"cli")}catch{}this.logFile=nt.join(Et.tmpdir(),`sinch-${n}.log`);try{re.writeFileSync(this.logFile,`=== Sinch CLI Debug Log - ${new Date().toISOString()} ===
5
+ For better security, export as environment variables instead:`)),console.log(Z.default.cyan(' export SINCH_KEY_SECRET="'+r+'"')),console.log(Z.default.cyan(' export SINCH_APPLICATION_SECRET="'+a+'"')),this.config.set("keySecretPlaintext",r),this.config.set("applicationSecretPlaintext",a)),this.config.set("projectId",n),this.config.set("keyId",i),this.config.set("defaultApplicationKey",s),this.config.set("credentialsStored",!0),await this.config.save()}async storeOAuthToken(e){let{access_token:n,refresh_token:i,expires_in:r,token_type:s}=e,a=new Date(Date.now()+r*1e3).toISOString(),c=await this.setPassword(`${U}-oauth-access`,n),l=!0;i&&(l=await this.setPassword(`${U}-oauth-refresh`,i)),this.config.set("oauthTokenType",s),this.config.set("oauthExpiresAt",a),this.config.set("oauthStored",c&&l),await this.config.save()}async reAuthenticateOAuth(){try{let e=await this.retrieve();if(!e)return null;let{SinchAPI:n}=(_(),D($e)),r=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(r),r.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(Z.default.gray("Token expired, re-authenticating..."));let i=await this.reAuthenticateOAuth();return i?console.log(Z.default.green("\u2713 Token renewed successfully")):console.warn(Z.default.yellow("Failed to renew OAuth token. Please login again.")),i}return await this.getPassword(`${U}-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,r=process.env.SINCH_APPLICATION_SECRET;if(e&&n&&i&&r)return{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId")||"",keyId:e,keySecret:n,applicationKey:i,applicationSecret:r};if(!this.config.get("credentialsStored"))return null;let a=this.config.get("projectId"),c=this.config.get("keyId"),l=this.config.get("defaultApplicationKey"),u=await this.getPassword(`${U}-keySecret`),g=l?await this.getPassword(l):null;return(!u||!g)&&(u=u||n||null,g=g||r||null),(!u||!g)&&(u=u||this.config.get("keySecretPlaintext"),g=g||this.config.get("applicationSecretPlaintext")),!u||!g?null:{projectId:a,keyId:c,keySecret:u,applicationKey:l,applicationSecret:g}}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(`${U}-keySecret`),await this.deletePassword(`${U}-oauth-access`),await this.deletePassword(`${U}-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(`${U}-keySecret`),r=this.config.get("defaultApplicationKey"),s=r?await this.getPassword(r):null;return!!(i&&s)}async hasOAuthToken(){return this.config.get("oauthStored")?!!await this.getPassword(`${U}-oauth-access`):!1}getPublicInfo(){return{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")}}async createSinchClient(e=null){let n=await this.getApplicationCredentials(e);if(!n)throw new Error('No credentials found. Please run "sinch auth login" first.');let{SinchClient:i}=require("@sinch/sdk-core");return new i({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret,projectId:this.config.get("projectId")})}async storeBasicAuthToken(e){await this.setPassword(`${U}-basic-auth`,e)&&(this.config.set("basicAuthStored",!0),await this.config.save())}async getBasicAuthToken(){return this.config.get("basicAuthStored")?await this.getPassword(`${U}-basic-auth`):null}async clearBasicAuthToken(){await this.deletePassword(`${U}-basic-auth`),this.config.set("basicAuthStored",!1),await this.config.save()}}});var fe={};Ue(fe,{Config:()=>Ve,config:()=>p});var W,Te,kt,Xe,Ve,p,A=de(()=>{"use strict";W=m(require("fs-extra")),Te=m(require("path")),kt=m(require("os")),Xe=m(require("chalk"));$t();Ve=class{configDir;configFile;projectConfigFile;_config=null;_projectConfig=null;_credentials=null;constructor(){this.configDir=Te.join(kt.homedir(),".sinch"),this.configFile=Te.join(this.configDir,"config.json"),this.projectConfigFile=Te.join(process.cwd(),"sinch.json")}async load(){try{await W.ensureDir(this.configDir),await W.pathExists(this.configFile)?this._config=await W.readJson(this.configFile):(this._config=this._getDefaultConfig(),await this.save())}catch(e){console.warn(Xe.default.yellow(`Warning: Could not load config: ${e.message}`)),this._config=this._getDefaultConfig()}this._credentials=new qe(this);try{await W.pathExists(this.projectConfigFile)&&(this._projectConfig=await W.readJson(this.projectConfigFile))}catch(e){console.warn(Xe.default.yellow(`Warning: Could not load project config: ${e.message}`))}}async save(){try{await W.ensureDir(this.configDir),await W.writeJson(this.configFile,this._config,{spaces:2})}catch(e){throw new Error(`Could not save config: ${e.message}`)}}async saveProjectConfig(){try{if(this._projectConfig){let e=Te.join(process.cwd(),"sinch.json");await W.writeJson(e,this._projectConfig,{spaces:2})}}catch(e){throw new Error(`Could not save project config: ${e.message}`)}}get(e,n=null){if(!this._config)throw new Error("Config not loaded. Call load() first.");return this._projectConfig&&this._projectConfig[e]!==void 0?this._projectConfig[e]:this._config[e]!==void 0?this._config[e]:n}set(e,n,i=!1){if(!this._config)throw new Error("Config not loaded. Call load() first.");i?(this._projectConfig||(this._projectConfig={}),this._projectConfig[e]=n):this._config[e]=n}getApiConfig(){return{apiUrl:this.get("apiUrl"),oauthUrl:this.get("oauthUrl","https://auth.sinch.com/oauth2/token"),projectId:this.get("projectId"),credentials:this._credentials}}async initProject(e,n="node",i={},r=null){let s={name:e,runtime:n,version:"1.0.0",description:`Sinch Functions project: ${e}`,created:new Date().toISOString()};return i&&Object.keys(i).length>0&&(s.variables=i),r&&(s.applicationKey=r),this._projectConfig=s,await this.saveProjectConfig(),s}isInProject(){return this._projectConfig!==null}getProjectConfig(){return this._projectConfig}_getDefaultConfig(){return{apiUrl:"https://api.functions.dev.sinchvoice.org",oauthUrl:"https://auth.sinch.com/oauth2/token",projectId:"default-project",created:new Date().toISOString(),version:"1.0.0"}}async storeCredentials(e){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.store(e)}async getCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.retrieve()}async clearCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.clear()}async hasCredentials(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.hasCredentials()}getPublicCredentialInfo(){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return this._credentials.getPublicInfo()}async createSinchClient(e=null){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return!e&&this.isInProject()&&(e=this._projectConfig?.applicationKey||null),await this._credentials.createSinchClient(e)}async getApplicationCredentials(e=null){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return!e&&this.isInProject()&&(e=this._projectConfig?.applicationKey||null),await this._credentials.getApplicationCredentials(e)}async storeApplicationSecret(e,n){if(!this._credentials)throw new Error("Config not loaded. Call load() first.");return await this._credentials.storeApplicationSecret(e,n)}getTunnelPreference(){return this._projectConfig&&this._projectConfig.tunnel?.preference||null}async setTunnelPreference(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.preference=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}getTunnelSubdomain(){return this._projectConfig&&this._projectConfig.tunnel?.subdomain||null}async setTunnelSubdomain(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.subdomain=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}getTunnelUrl(){return this._projectConfig&&this._projectConfig.tunnel?.lastUrl||null}async setTunnelUrl(e){if(!this._projectConfig)throw new Error("Not in a project directory");this._projectConfig.tunnel||(this._projectConfig.tunnel={}),this._projectConfig.tunnel.lastUrl=e,this._projectConfig.tunnel.lastUpdated=new Date().toISOString(),await this.saveProjectConfig()}},p=new Ve});var H,re,et,Pt,tt,t,B=de(()=>{"use strict";H=m(require("chalk")),re=m(require("fs")),et=m(require("path")),Pt=m(require("os")),tt=class{verbose;logFile;constructor(e={}){this.verbose=e.verbose||process.env.VERBOSE==="true";let n="cli";try{let i=et.join(process.cwd(),"sinch.json");re.existsSync(i)&&(n=JSON.parse(re.readFileSync(i,"utf8")).name||"cli")}catch{}this.logFile=et.join(Pt.tmpdir(),`sinch-${n}.log`);try{re.writeFileSync(this.logFile,`=== Sinch CLI Debug Log - ${new Date().toISOString()} ===
6
6
  `,{flag:"w"})}catch{}}writeToFile(e,n,...i){try{let s=`[${new Date().toISOString()}] ${e}: ${n} ${i.length>0?JSON.stringify(i):""}
7
7
  `;re.appendFileSync(this.logFile,s)}catch{}}info(e,...n){console.log(H.default.blue("\u2139"),e,...n),this.writeToFile("INFO",e,...n)}success(e,...n){console.log(H.default.green("\u2705"),e,...n),this.writeToFile("SUCCESS",e,...n)}warn(e,...n){console.log(H.default.yellow("\u26A0\uFE0F "),e,...n),this.writeToFile("WARN",e,...n)}error(e,...n){console.log(H.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(H.default.gray("\u{1F41B}"),H.default.gray(e),...n)}log(e,...n){console.log(e,...n)}title(e){console.log(H.default.blue.bold(`
8
8
  \u{1F3AF} ${e}`))}subtitle(e){console.log(H.default.gray(`
9
- ${e}`))}list(e,n={}){let{indent:i=" ",bullet:r="\u2022"}=n;e.forEach(s=>{console.log(`${i}${H.default.gray(r)} ${s}`)})}table(e,n){let i=e.map(s=>s.length);n.forEach(s=>{s.forEach((a,c)=>{i[c]=Math.max(i[c]??0,String(a).length)})});let r=e.map((s,a)=>s.padEnd(i[a]??0)).join(" ");console.log(H.default.bold(r)),console.log(H.default.gray("-".repeat(r.length))),n.forEach(s=>{let a=s.map((c,l)=>String(c).padEnd(i[l]??0)).join(" ");console.log(a)})}newline(){console.log()}},t=new ot});var Pe={};Be(Pe,{Spinner:()=>We,spinner:()=>d});var It,Rt,We,d,j=fe(()=>{"use strict";It=m(require("ora")),Rt=m(require("cli-spinners")),We=class{spinner=null;spinnerType=Rt.default.dots;start(e){return this.spinner=(0,It.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)}},d=new We});var Ot=N((Ri,Ft)=>{"use strict";var x=m(require("fs-extra")),ye=m(require("path")),B=m(require("chalk")),Ae=m(require("inquirer")),Tt=require("commander");I();K();j();L();var Oe=require("child_process"),Dt=m(require("adm-zip")),jt=new Tt.Command("init");jt.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(o,e)=>{try{await p.load();let n=process.cwd(),i=new A(p.getApiConfig()),r=e.runtime;r||(e.nonInteractive?r="node":r=(await Ae.default.prompt([{type:"list",name:"runtime",message:"Choose a runtime:",choices:[{name:"Node.js",value:"node"},{name:"C# (.NET)",value:"csharp"}],default:"node"}])).runtime),d.start(`Fetching available templates for ${r}...`);let s=await i.listRuntimeTemplates(r);if(d.stop(),!s.templates||s.templates.length===0)throw new Error(`No templates available for runtime '${r}'`);let a=o;if(!a)if(e.nonInteractive){let C=s.templates.filter(b=>b.name&&b.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=s.templates.filter(y=>y.name&&y.name.trim()).map(y=>({name:`${y.name} - ${(y.description||"No description available").substring(0,100)}`,value:y.name}));a=(await Ae.default.prompt([{type:"list",name:"selectedTemplate",message:"Choose a template:",choices:C,pageSize:10}])).selectedTemplate}let c=e.name;c||(e.nonInteractive?c=a:c=(await Ae.default.prompt([{type:"input",name:"name",message:"Function name:",default:a,validate:b=>!b||b.trim().length===0?"Function name is required":/^[a-z][a-z0-9-]*$/.test(b.trim())?!0:"Function name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens"}])).name.trim());let l=ye.default.join(n,c);if(await x.default.pathExists(l)){let C=!1;if(e.nonInteractive?(C=!0,t.info(`Directory '${c}' already exists. Overwriting (non-interactive mode)...`)):C=(await Ae.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${c}' already exists. Overwrite?`,default:!1}])).overwrite,!C){t.info("Initialization cancelled");return}await x.default.remove(l)}await x.default.ensureDir(l);let u=s.templates.find(C=>C.name===a);if(!u){let C=s.templates.map(b=>b.name).join(", ");throw new Error(`Template '${a}' not found. Available templates: ${C}`)}let g=["node","csharp"];if(!g.includes(r))throw new Error(`Runtime '${r}' not supported. Supported runtimes: ${g.join(", ")}`);d.start(`\u{1F680} Initializing ${c} with ${a} template (${r})...`);let h=await i.downloadTemplate(r,a);new Dt.default(h).extractAllTo(l,!0),d.succeed("\u{1F4E6} Template extracted");let w={},T=ye.default.join(l,"template.json");if(await x.default.pathExists(T)){let C=await x.default.readJson(T);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,y]of Object.entries(C.variables)){let P;typeof y=="string"?P=y:P=y.default||"",w[b]=P,t.info(` ${b}: ${P}`)}}else{t.newline(),t.info("\u{1F4DD} Configure template variables:");for(let[b,y]of Object.entries(C.variables)){let P;typeof y=="string"?P={type:"input",name:b,message:`${b.replace(/_/g," ").toLowerCase()}:`,default:y}:(P={type:y.type==="number"?"number":"input",name:b,message:`${y.description||b.replace(/_/g," ").toLowerCase()}:`,default:y.default},y.type==="number"&&(P.validate=E=>y.min!==void 0&&E<y.min?`Value must be at least ${y.min}`:y.max!==void 0&&E>y.max?`Value must be at most ${y.max}`:!0));let Q=await Ae.default.prompt([P]);w[b]=Q[b]}}await x.default.remove(T)}d.start("\u{1F527} Finalizing function configuration...");let q=ye.default.join(l,"sinch.json"),$;if(await x.default.pathExists(q)){if($=await x.default.readJson(q),$.name=c,$.description=`Sinch Functions function: ${c}`,$.functionId=null,delete $.projectId,delete $.voiceAppId,$.variables)for(let[C,b]of Object.entries($.variables))typeof b=="string"&&(b==="your-project-id"||b==="{{PROJECT_ID}}"?$.variables[C]=p.get("projectId"):(b==="your-application-key"||b==="{{SINCH_APPLICATION_KEY}}")&&($.variables[C]=p.get("defaultApplicationKey")));$.created=new Date().toISOString(),Object.keys(w).length>0&&($.variables={...$.variables,...w}),$.secrets&&delete $.secrets}else $={name:c,functionId:null,runtime:r,version:"1.0.0",description:`Sinch Functions function: ${c}`,created:new Date().toISOString(),variables:w,custom:{}};if(await x.default.writeJson(q,$,{spaces:2}),r==="node"){let C=ye.default.join(l,"package.json");if(await x.default.pathExists(C)){let D=await x.default.readJson(C);D.name=c,D.description=$.description,await x.default.writeJson(C,D,{spaces:2})}let b=ye.default.join(l,".env"),y=`# Sinch Functions Environment Variables
9
+ ${e}`))}list(e,n={}){let{indent:i=" ",bullet:r="\u2022"}=n;e.forEach(s=>{console.log(`${i}${H.default.gray(r)} ${s}`)})}table(e,n){let i=e.map(s=>s.length);n.forEach(s=>{s.forEach((a,c)=>{i[c]=Math.max(i[c]??0,String(a).length)})});let r=e.map((s,a)=>s.padEnd(i[a]??0)).join(" ");console.log(H.default.bold(r)),console.log(H.default.gray("-".repeat(r.length))),n.forEach(s=>{let a=s.map((c,l)=>String(c).padEnd(i[l]??0)).join(" ");console.log(a)})}newline(){console.log()}},t=new tt});var ke={};Ue(ke,{Spinner:()=>Je,spinner:()=>d});var Et,It,Je,d,F=de(()=>{"use strict";Et=m(require("ora")),It=m(require("cli-spinners")),Je=class{spinner=null;spinnerType=It.default.dots;start(e){return this.spinner=(0,Et.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)}},d=new Je});var Dt=N((Ii,jt)=>{"use strict";var x=m(require("fs-extra")),ge=m(require("path")),K=m(require("chalk")),Pe=m(require("inquirer")),At=require("commander");A();B();F();_();var je=require("child_process"),Rt=m(require("adm-zip")),Tt=new At.Command("init");Tt.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(o,e)=>{try{await p.load();let n=process.cwd(),i=new E(p.getApiConfig()),r=e.runtime;r||(e.nonInteractive?r="node":r=(await Pe.default.prompt([{type:"list",name:"runtime",message:"Choose a runtime:",choices:[{name:"Node.js",value:"node"},{name:"C# (.NET)",value:"csharp"}],default:"node"}])).runtime),d.start(`Fetching available templates for ${r}...`);let s=await i.listRuntimeTemplates(r);if(d.stop(),!s.templates||s.templates.length===0)throw new Error(`No templates available for runtime '${r}'`);let a=o;if(!a)if(e.nonInteractive){let b=s.templates.filter(C=>C.name&&C.name.trim());if(b.length>0)a=b[0]?.name||"",t.info(`Using default template: ${a} (non-interactive mode)`);else throw new Error("No templates available")}else{let b=s.templates.filter(y=>y.name&&y.name.trim()).map(y=>({name:`${y.name} - ${(y.description||"No description available").substring(0,100)}`,value:y.name}));a=(await Pe.default.prompt([{type:"list",name:"selectedTemplate",message:"Choose a template:",choices:b,pageSize:10}])).selectedTemplate}let c=e.name;c||(e.nonInteractive?c=a:c=(await Pe.default.prompt([{type:"input",name:"name",message:"Function name:",default:a,validate:C=>!C||C.trim().length===0?"Function name is required":/^[a-z][a-z0-9-]*$/.test(C.trim())?!0:"Function name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens"}])).name.trim());let l=ge.default.join(n,c);if(await x.default.pathExists(l)){let b=!1;if(e.nonInteractive?(b=!0,t.info(`Directory '${c}' already exists. Overwriting (non-interactive mode)...`)):b=(await Pe.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${c}' already exists. Overwrite?`,default:!1}])).overwrite,!b){t.info("Initialization cancelled");return}await x.default.remove(l)}await x.default.ensureDir(l);let u=s.templates.find(b=>b.name===a);if(!u){let b=s.templates.map(C=>C.name).join(", ");throw new Error(`Template '${a}' not found. Available templates: ${b}`)}let g=["node","csharp"];if(!g.includes(r))throw new Error(`Runtime '${r}' not supported. Supported runtimes: ${g.join(", ")}`);d.start(`\u{1F680} Initializing ${c} with ${a} template (${r})...`);let h=await i.downloadTemplate(r,a);new Rt.default(h).extractAllTo(l,!0),d.succeed("\u{1F4E6} Template extracted");let w={},T=ge.default.join(l,"template.json");if(await x.default.pathExists(T)){let b=await x.default.readJson(T);if(b.variables&&Object.keys(b.variables).length>0)if(e.nonInteractive){t.info("\u{1F4DD} Using default values for template variables (non-interactive mode):");for(let[C,y]of Object.entries(b.variables)){let P;typeof y=="string"?P=y:P=y.default||"",w[C]=P,t.info(` ${C}: ${P}`)}}else{t.newline(),t.info("\u{1F4DD} Configure template variables:");for(let[C,y]of Object.entries(b.variables)){let P;typeof y=="string"?P={type:"input",name:C,message:`${C.replace(/_/g," ").toLowerCase()}:`,default:y}:(P={type:y.type==="number"?"number":"input",name:C,message:`${y.description||C.replace(/_/g," ").toLowerCase()}:`,default:y.default},y.type==="number"&&(P.validate=I=>y.min!==void 0&&I<y.min?`Value must be at least ${y.min}`:y.max!==void 0&&I>y.max?`Value must be at most ${y.max}`:!0));let Q=await Pe.default.prompt([P]);w[C]=Q[C]}}await x.default.remove(T)}d.start("\u{1F527} Finalizing function configuration...");let V=ge.default.join(l,"sinch.json"),$;if(await x.default.pathExists(V)){if($=await x.default.readJson(V),$.name=c,$.description=`Sinch Functions function: ${c}`,$.functionId=null,delete $.projectId,delete $.voiceAppId,$.variables)for(let[b,C]of Object.entries($.variables))typeof C=="string"&&(C==="your-project-id"||C==="{{PROJECT_ID}}"?$.variables[b]=p.get("projectId"):(C==="your-application-key"||C==="{{SINCH_APPLICATION_KEY}}")&&($.variables[b]=p.get("defaultApplicationKey")));$.created=new Date().toISOString(),Object.keys(w).length>0&&($.variables={...$.variables,...w}),$.secrets&&delete $.secrets}else $={name:c,functionId:null,runtime:r,version:"1.0.0",description:`Sinch Functions function: ${c}`,created:new Date().toISOString(),variables:w,custom:{}};if(await x.default.writeJson(V,$,{spaces:2}),r==="node"){let b=ge.default.join(l,"package.json");if(await x.default.pathExists(b)){let j=await x.default.readJson(b);j.name=c,j.description=$.description,await x.default.writeJson(b,j,{spaces:2})}let C=ge.default.join(l,".env"),y=`# Sinch Functions Environment Variables
10
10
  `;y+=`# Generated by sinch functions init
11
11
 
12
12
  `,y+=`# Template Variables
13
- `,Object.keys(w).forEach(D=>{y+=`${D}=${w[D]}
14
- `});let P=p.get("projectId"),Q=p.get("functionId"),E=p.get("defaultApplicationKey"),pe=p.get("keyId");y+=`
13
+ `,Object.keys(w).forEach(j=>{y+=`${j}=${w[j]}
14
+ `});let P=p.get("projectId"),Q=p.get("functionId"),I=p.get("defaultApplicationKey"),ue=p.get("keyId");y+=`
15
15
  # Sinch Configuration
16
16
  `,y+=`PROJECT_ID=${P||""}
17
17
  `,y+=`FUNCTION_ID=${Q||""}
18
- `,y+=`PROJECT_ID_API_KEY=${pe||""}
19
- `,y+=`VOICE_APPLICATION_KEY=${E||""}
18
+ `,y+=`PROJECT_ID_API_KEY=${ue||""}
19
+ `,y+=`VOICE_APPLICATION_KEY=${I||""}
20
20
  `,y+=`PROTECT_VOICE_CALLBACKS=deploy
21
21
  `,y+=`
22
22
  # Secrets (stored in OS keychain - use "sinch auth login" to configure)
@@ -26,11 +26,11 @@ ${e}`))}list(e,n={}){let{indent:i=" ",bullet:r="\u2022"}=n;e.forEach(s=>{consol
26
26
  # Environment
27
27
  `,y+=`NODE_ENV=development
28
28
  `,y+=`PORT=3000
29
- `,await x.default.writeFile(b,y),t.info(""),t.info("\u{1F510} Secrets Management for Node.js:");try{let D=await p.getCredentials();D&&D.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(` ${B.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(` ${B.default.cyan("sinch auth login")}`),t.info(""),t.info(" To add custom secrets:"),t.info(` ${B.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`))}catch{t.info(" \u2139\uFE0F Set up authentication with:"),t.info(` ${B.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(r==="csharp"){let C=ye.default.join(l,"appsettings.json"),b={Logging:{LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}},AllowedHosts:"*"};Object.keys(w).forEach(E=>{b[E]=w[E]});let y=p.get("projectId"),P=p.get("defaultApplicationKey"),Q=p.get("keyId");b.PROJECT_ID=y||"",b.PROJECT_ID_API_KEY=Q||"",b.PROJECT_ID_API_SECRET="",b.VOICE_APPLICATION_KEY=P||"",b.VOICE_APPLICATION_SECRET="",b.PROTECT_VOICE_CALLBACKS="deploy",await x.default.writeJson(C,b,{spaces:2});try{let E=await p.getCredentials();await new Promise((pe,D)=>{let ie=(0,Oe.spawn)("dotnet",["user-secrets","init"],{cwd:l,shell:!0});ie.on("close",Te=>Te===0?pe():D(new Error("Failed to init user-secrets"))),ie.on("error",D)}),E&&E.keySecret&&await new Promise((pe,D)=>{let ie=(0,Oe.spawn)("dotnet",["user-secrets","set","PROJECT_ID_API_SECRET",E.keySecret],{cwd:l,shell:!0});ie.on("close",Te=>Te===0?pe():D(new Error("Failed to set API secret"))),ie.on("error",D)}),E&&E.applicationSecret&&await new Promise((pe,D)=>{let ie=(0,Oe.spawn)("dotnet",["user-secrets","set","VOICE_APPLICATION_SECRET",E.applicationSecret],{cwd:l,shell:!0});ie.on("close",Te=>Te===0?pe():D(new Error("Failed to set app secret"))),ie.on("error",D)}),E&&(E.keySecret||E.applicationSecret)&&(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: "+B.default.cyan("dotnet user-secrets list")))}catch{t.info(""),t.info("\u{1F510} Secrets Management for C#:"),t.info(" For local development, use dotnet user-secrets:"),t.info(` ${B.default.cyan("dotnet user-secrets init")}`),t.info(` ${B.default.cyan('dotnet user-secrets set "PROJECT_ID_API_SECRET" "your-api-secret"')}`),t.info(` ${B.default.cyan('dotnet user-secrets set "VOICE_APPLICATION_SECRET" "your-app-secret"')}`)}}if(d.succeed("\u{1F680} Function initialized successfully"),t.newline(),t.title(`Function: ${B.default.cyan(c)}`),t.info(`Template: ${B.default.yellow(a)}`),t.info(`Runtime: ${B.default.blue(r)}`),t.info(`Location: ${B.default.gray(l)}`),r==="node"&&!e.skipInstall){t.newline(),d.start("Installing npm packages...");try{await new Promise((C,b)=>{let y=(0,Oe.spawn)("npm",["install"],{cwd:l,stdio:"inherit",shell:!0});y.on("close",P=>{P===0?C():b(new Error(`npm install failed with code ${P}`))}),y.on("error",P=>{b(P)})}),d.succeed("\u{1F4E6} Dependencies installed successfully")}catch(C){d.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: ${B.default.cyan(`cd ${c}`)}`),r==="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 ${u.description}`),u.features&&u.features.length>0&&u.features.forEach(C=>{t.info(`\u2022 ${C}`)})}catch(n){d.stop(),t.error(`Failed to initialize function: ${n.message}`),process.exit(1)}});Ft.exports=jt});var Ut=N((Oi,Nt)=>{"use strict";var k=m(require("chalk")),Lt=require("commander"),xt=m(require("cli-table3")),Le=m(require("inquirer"));L();I();K();j();var _t=new Lt.Command("list");_t.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 o=>{try{await p.load();let e=new A(p.getApiConfig());d.start("\u{1F4CB} Loading functions...");let n={limit:parseInt(o.limit||"50")};o.status&&(n.status=o.status),o.runtime&&(n.runtime=o.runtime);let i=await e.listFunctions();if(d.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(` ${k.default.cyan("sinch functions init")}`);return}t.newline(),t.title("Functions:");let r=i.functions.map(a=>{let c=new Date(a.createdAt).toLocaleDateString(),l=it(a.status),u=a.containerAppUrl?a.containerAppUrl.length>40?a.containerAppUrl.substring(0,37)+"...":a.containerAppUrl:k.default.gray("Not deployed");return[k.default.cyan(a.name),k.default.yellow(a.runtime),l,k.default.gray(c),k.default.blue(u)]}),s=new xt.default({head:["Name","Runtime","Status","Created","URL"],style:{head:["cyan"]},colWidths:[20,10,15,12,45]});if(s.push(...r),console.log(s.toString()),i.pagination){let{page:a,totalCount:c,totalPages:l}=i.pagination;t.newline(),t.info(k.default.gray(`Page ${a} of ${l} (${c} total functions)`)),a<l&&t.info(k.default.gray("\u{1F4A1} Use --limit to see more results"))}if(o.interactive&&i.functions.length>0){t.newline();let a=i.functions.map(u=>({name:`${u.name.padEnd(20)} ${u.runtime.padEnd(8)} ${it(u.status).padEnd(20)} ${u.id.substring(0,8)}`,value:u.id,short:u.name}));a.push(new Le.default.Separator),a.push({name:k.default.gray("Exit"),value:"exit",short:"Exit"});let{selectedFunction:c}=await Le.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function for actions:",choices:a,pageSize:15}]);if(c==="exit")return;let l=i.functions.find(u=>u.id===c);l&&await uo(l,e)}else t.newline(),t.info("\u{1F4A1} Function commands:"),t.info(` \u2022 View details: ${k.default.cyan("sinch functions status 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 View logs: ${k.default.cyan("sinch functions logs 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Download: ${k.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Interactive mode: ${k.default.cyan("sinch functions list -i")}`),t.info(` \u2022 Deploy new function: ${k.default.cyan("sinch functions deploy")}`)}catch(e){d.stop(),t.error(`Failed to list functions: ${e.message}`),process.exit(1)}});function it(o){return{Running:k.default.green("\u2705 Running"),Failed:k.default.red("\u274C Failed"),Pending:k.default.yellow("\u23F3 Pending"),Building:k.default.blue("\u{1F528} Building")}[o]||k.default.gray(o)}async function uo(o,e){t.newline(),t.info(`\u{1F4CB} Selected: ${k.default.cyan(o.name)}`),t.info(` ID: ${k.default.gray(o.id)}`),t.info(` Status: ${it(o.status)}`),t.newline();let{action:n}=await Le.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 Le.default.Separator,{name:k.default.gray("Back"),value:"back"}]}]);switch(n){case"download":t.info(`
29
+ `,await x.default.writeFile(C,y),t.info(""),t.info("\u{1F510} Secrets Management for Node.js:");try{let j=await p.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(` ${K.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(` ${K.default.cyan("sinch auth login")}`),t.info(""),t.info(" To add custom secrets:"),t.info(` ${K.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`))}catch{t.info(" \u2139\uFE0F Set up authentication with:"),t.info(` ${K.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(r==="csharp"){let b=ge.default.join(l,"appsettings.json"),C={Logging:{LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}},AllowedHosts:"*"};Object.keys(w).forEach(I=>{C[I]=w[I]});let y=p.get("projectId"),P=p.get("defaultApplicationKey"),Q=p.get("keyId");C.PROJECT_ID=y||"",C.PROJECT_ID_API_KEY=Q||"",C.PROJECT_ID_API_SECRET="",C.VOICE_APPLICATION_KEY=P||"",C.VOICE_APPLICATION_SECRET="",C.PROTECT_VOICE_CALLBACKS="deploy",await x.default.writeJson(b,C,{spaces:2});try{let I=await p.getCredentials();await new Promise((ue,j)=>{let ie=(0,je.spawn)("dotnet",["user-secrets","init"],{cwd:l,shell:!0});ie.on("close",Ae=>Ae===0?ue():j(new Error("Failed to init user-secrets"))),ie.on("error",j)}),I&&I.keySecret&&await new Promise((ue,j)=>{let ie=(0,je.spawn)("dotnet",["user-secrets","set","PROJECT_ID_API_SECRET",I.keySecret],{cwd:l,shell:!0});ie.on("close",Ae=>Ae===0?ue():j(new Error("Failed to set API secret"))),ie.on("error",j)}),I&&I.applicationSecret&&await new Promise((ue,j)=>{let ie=(0,je.spawn)("dotnet",["user-secrets","set","VOICE_APPLICATION_SECRET",I.applicationSecret],{cwd:l,shell:!0});ie.on("close",Ae=>Ae===0?ue():j(new Error("Failed to set app secret"))),ie.on("error",j)}),I&&(I.keySecret||I.applicationSecret)&&(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: "+K.default.cyan("dotnet user-secrets list")))}catch{t.info(""),t.info("\u{1F510} Secrets Management for C#:"),t.info(" For local development, use dotnet user-secrets:"),t.info(` ${K.default.cyan("dotnet user-secrets init")}`),t.info(` ${K.default.cyan('dotnet user-secrets set "PROJECT_ID_API_SECRET" "your-api-secret"')}`),t.info(` ${K.default.cyan('dotnet user-secrets set "VOICE_APPLICATION_SECRET" "your-app-secret"')}`)}}if(d.succeed("\u{1F680} Function initialized successfully"),t.newline(),t.title(`Function: ${K.default.cyan(c)}`),t.info(`Template: ${K.default.yellow(a)}`),t.info(`Runtime: ${K.default.blue(r)}`),t.info(`Location: ${K.default.gray(l)}`),r==="node"&&!e.skipInstall){t.newline(),d.start("Installing npm packages...");try{await new Promise((b,C)=>{let y=(0,je.spawn)("npm",["install"],{cwd:l,stdio:"inherit",shell:!0});y.on("close",P=>{P===0?b():C(new Error(`npm install failed with code ${P}`))}),y.on("error",P=>{C(P)})}),d.succeed("\u{1F4E6} Dependencies installed successfully")}catch(b){d.fail("\u{1F4E6} Failed to install dependencies"),b.code==="ENOENT"?t.warn("npm not found. Please ensure Node.js is installed and in your PATH."):t.debug(`npm install error: ${b.message}`)}}t.newline(),t.info("\u{1F4CB} Next steps:"),t.info(` 1. \u{1F4C1} Navigate to function: ${K.default.cyan(`cd ${c}`)}`),r==="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 ${u.description}`),u.features&&u.features.length>0&&u.features.forEach(b=>{t.info(`\u2022 ${b}`)})}catch(n){d.stop(),t.error(`Failed to initialize function: ${n.message}`),process.exit(1)}});jt.exports=Tt});var Lt=N((Di,xt)=>{"use strict";var k=m(require("chalk")),Ft=require("commander"),Ot=m(require("cli-table3")),De=m(require("inquirer"));_();A();B();F();var _t=new Ft.Command("list");_t.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 o=>{try{await p.load();let e=new E(p.getApiConfig());d.start("\u{1F4CB} Loading functions...");let n={limit:parseInt(o.limit||"50")};o.status&&(n.status=o.status),o.runtime&&(n.runtime=o.runtime);let i=await e.listFunctions();if(d.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(` ${k.default.cyan("sinch functions init")}`);return}t.newline(),t.title("Functions:");let r=i.functions.map(a=>{let c=new Date(a.createdAt).toLocaleDateString(),l=nt(a.status),u=a.containerAppUrl?a.containerAppUrl.length>40?a.containerAppUrl.substring(0,37)+"...":a.containerAppUrl:k.default.gray("Not deployed");return[k.default.cyan(a.name),k.default.yellow(a.runtime),l,k.default.gray(c),k.default.blue(u)]}),s=new Ot.default({head:["Name","Runtime","Status","Created","URL"],style:{head:["cyan"]},colWidths:[20,10,15,12,45]});if(s.push(...r),console.log(s.toString()),i.pagination){let{page:a,totalCount:c,totalPages:l}=i.pagination;t.newline(),t.info(k.default.gray(`Page ${a} of ${l} (${c} total functions)`)),a<l&&t.info(k.default.gray("\u{1F4A1} Use --limit to see more results"))}if(o.interactive&&i.functions.length>0){t.newline();let a=i.functions.map(u=>({name:`${u.name.padEnd(20)} ${u.runtime.padEnd(8)} ${nt(u.status).padEnd(20)} ${u.id.substring(0,8)}`,value:u.id,short:u.name}));a.push(new De.default.Separator),a.push({name:k.default.gray("Exit"),value:"exit",short:"Exit"});let{selectedFunction:c}=await De.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function for actions:",choices:a,pageSize:15}]);if(c==="exit")return;let l=i.functions.find(u=>u.id===c);l&&await ao(l,e)}else t.newline(),t.info("\u{1F4A1} Function commands:"),t.info(` \u2022 View details: ${k.default.cyan("sinch functions status 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 View logs: ${k.default.cyan("sinch functions logs 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Download: ${k.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Interactive mode: ${k.default.cyan("sinch functions list -i")}`),t.info(` \u2022 Deploy new function: ${k.default.cyan("sinch functions deploy")}`)}catch(e){d.stop(),t.error(`Failed to list functions: ${e.message}`),process.exit(1)}});function nt(o){return{Running:k.default.green("\u2705 Running"),Failed:k.default.red("\u274C Failed"),Pending:k.default.yellow("\u23F3 Pending"),Building:k.default.blue("\u{1F528} Building")}[o]||k.default.gray(o)}async function ao(o,e){t.newline(),t.info(`\u{1F4CB} Selected: ${k.default.cyan(o.name)}`),t.info(` ID: ${k.default.gray(o.id)}`),t.info(` Status: ${nt(o.status)}`),t.newline();let{action:n}=await De.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 De.default.Separator,{name:k.default.gray("Back"),value:"back"}]}]);switch(n){case"download":t.info(`
30
30
  \u{1F4A1} To download this function, run:`),t.info(` ${k.default.cyan(`sinch functions download ${o.id}`)}`);break;case"status":t.info(`
31
31
  \u{1F4A1} To view status, run:`),t.info(` ${k.default.cyan(`sinch functions status ${o.id}`)}`);break;case"logs":t.info(`
32
32
  \u{1F4A1} To view logs, run:`),t.info(` ${k.default.cyan(`sinch functions logs ${o.id}`)}`);break;case"copy-url":o.containerAppUrl?(await require("clipboardy").write(o.containerAppUrl),t.success(`\u2705 URL copied to clipboard: ${o.containerAppUrl}`)):t.warn("\u26A0\uFE0F Function has no URL (not deployed)");break;case"delete":t.info(`
33
- \u{1F4A1} To delete this function, run:`),t.info(` ${k.default.cyan(`sinch functions delete ${o.id}`)}`);break;case"back":return}}Nt.exports=_t});async function st(o){if(!await p.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let e=await p.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}/`,r={url:{primary:o}},s=`${e.applicationKey}:${e.applicationSecret}`,a=Buffer.from(s).toString("base64");await rt.default.post(i,r,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/json"},timeout:1e4}),await new Promise(g=>setTimeout(g,1e3));let u=(await rt.default.get(i,{headers:{Authorization:`Basic ${a}`},timeout:1e4})).data?.url?.primary;if(u!==o)throw t.debug(`Callback verification mismatch. Expected: ${o}, Got: ${u}`),new Error(`Callback URL update verification failed. Expected: ${o}, Got: ${u}`);t.debug("Voice callback URL successfully updated and verified")}var rt,Kt=fe(()=>{"use strict";rt=m(require("axios"));I();K()});var Mt={};Be(Mt,{combineDocumentation:()=>Vt,detectRuntimeFromFile:()=>qt,findFunctionFile:()=>Bt,generateDocsFromLocal:()=>at,saveDocumentationToFile:()=>ct});async function at(){let o=process.cwd(),e=await Bt(o);if(!e)throw new Error("No function file found. Make sure you're in a function directory with function.js, index.js, or handler.js");let n=await Ee.readFile(e,"utf8"),i=qt(e),r=se.basename(o),a=await new A(p.getApiConfig()).generateDocumentationFromCode(n,i,r);return Vt(a)}async function Bt(o){let e=["function.js","index.js","handler.js","function.py","handler.py","Function.cs","Handler.cs"];for(let n of e){let i=se.join(o,n);if(await Ee.pathExists(i))return i}return null}function Vt(o){let e=o.documentation||"",n=o.diagram||o.callFlowDiagram;return n&&(e&&!e.endsWith(`
33
+ \u{1F4A1} To delete this function, run:`),t.info(` ${k.default.cyan(`sinch functions delete ${o.id}`)}`);break;case"back":return}}xt.exports=_t});async function it(o){if(!await p.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let e=await p.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}/`,r={url:{primary:o}},s=`${e.applicationKey}:${e.applicationSecret}`,a=Buffer.from(s).toString("base64");await ot.default.post(i,r,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/json"},timeout:1e4}),await new Promise(g=>setTimeout(g,1e3));let u=(await ot.default.get(i,{headers:{Authorization:`Basic ${a}`},timeout:1e4})).data?.url?.primary;if(u!==o)throw t.debug(`Callback verification mismatch. Expected: ${o}, Got: ${u}`),new Error(`Callback URL update verification failed. Expected: ${o}, Got: ${u}`);t.debug("Voice callback URL successfully updated and verified")}var ot,Nt=de(()=>{"use strict";ot=m(require("axios"));A();B()});var qt={};Ue(qt,{combineDocumentation:()=>Bt,detectRuntimeFromFile:()=>Kt,findFunctionFile:()=>Ut,generateDocsFromLocal:()=>rt,saveDocumentationToFile:()=>st});async function rt(){let o=process.cwd(),e=await Ut(o);if(!e)throw new Error("No function file found. Make sure you're in a function directory with function.js, index.js, or handler.js");let n=await Ee.readFile(e,"utf8"),i=Kt(e),r=se.basename(o),a=await new E(p.getApiConfig()).generateDocumentationFromCode(n,i,r);return Bt(a)}async function Ut(o){let e=["function.js","index.js","handler.js","function.py","handler.py","Function.cs","Handler.cs"];for(let n of e){let i=se.join(o,n);if(await Ee.pathExists(i))return i}return null}function Bt(o){let e=o.documentation||"",n=o.diagram||o.callFlowDiagram;return n&&(e&&!e.endsWith(`
34
34
 
35
35
  `)&&(e+=`
36
36
 
@@ -40,44 +40,44 @@ ${e}`))}list(e,n={}){let{indent:i=" ",bullet:r="\u2022"}=n;e.forEach(s=>{consol
40
40
  ---
41
41
 
42
42
  `,e+=`*Documentation generated on ${new Date(o.generatedAt).toLocaleString()} using Sinch AI*
43
- `),e}async function ct(o,e){let n=se.resolve(e);await Ee.writeFile(n,o,"utf8")}function qt(o){switch(se.extname(o).toLowerCase()){case".js":return"node";case".py":return"python";case".cs":return"csharp";default:return"node"}}var Ee,se,lt=fe(()=>{"use strict";Ee=m(require("fs-extra")),se=m(require("path"));L();I()});var Xt=N((Ji,Zt)=>{"use strict";var X=m(require("fs-extra")),we=m(require("path")),v=m(require("chalk")),Wt=require("commander");L();I();K();j();Kt();var Ht=m(require("adm-zip")),Gt=m(require("os")),Yt=m(require("inquirer")),zt=require("child_process"),Qt=new Wt.Command("deploy");Qt.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)").action(async o=>{try{if(await p.load(),!p.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=p.getProjectConfig(),n=o.name||e.name,i=e.runtime;await mo(e,o),d.start("\u{1F4E6} Packaging function...");let r=await po(n);d.succeed("\u{1F4E6} Function packaged"),d.start("\u{1F527} Preparing configuration...");let s=await fo(i);d.succeed("\u{1F527} Configuration prepared"),d.start("\u{1F680} Submitting deployment...");let a=new A(p.getApiConfig()),c=await X.default.readFile(r),l=await a.deployFunction(n,i,c,s);if(await X.default.remove(r),d.succeed("\u{1F680} Deployment submitted"),p.set("functionId",l.id,!0),await p.saveProjectConfig(),t.newline(),t.info(`Function ID: ${v.default.cyan(l.id)}`),t.info(`Status: ${ut(l.status)}`),o.wait===!1){t.newline(),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${v.default.cyan(`sinch functions status ${l.id}`)}`);return}await go(a,l.id)}catch(e){d.stop(),t.error(`Failed to deploy function: ${e.message}`),process.exit(1)}});async function po(o){let e=new Ht.default,n=process.cwd(),i=we.default.join(Gt.default.tmpdir(),`${o}-${Date.now()}.zip`),r=["node_modules","bin","obj",".git",".DS_Store","*.zip",".env",".env.local","npm-debug.log*",".sinch-tmp","examples","claude.md","readme.md"];async function s(a,c=""){let l=await X.default.readdir(a);for(let u of l){let g=we.default.join(a,u),h=we.default.join(c,u).replace(/\\/g,"/");if(r.some(w=>u.match(new RegExp(w.replace("*",".*")))))continue;if((await X.default.stat(g)).isDirectory())await s(g,h);else{let w=await X.default.readFile(g);e.addFile(h,w)}}}return await s(n),e.writeZip(i),i}async function fo(o){let e={},n=null;try{n=await p.getCredentials()}catch(i){t.debug("Could not load credentials from secure storage: "+i.message)}if(o==="csharp"){let i=we.default.join(process.cwd(),"appsettings.json");if(await X.default.pathExists(i))try{let r=await X.default.readJson(i);for(let s of Object.keys(r)){if(s==="Logging"||s==="AllowedHosts")continue;let a=r[s];if(a===""||a===null||a===void 0){let c="",l=!1;try{let u=(0,zt.execSync)(`dotnet user-secrets get "${s}"`,{cwd:process.cwd(),encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim();u&&!u.includes("No secrets configured")&&!u.includes("was not found")&&(c=u,l=!0,t.debug(`Found ${s} in dotnet user-secrets`))}catch{}!c&&n&&(s==="PROJECT_ID"&&n.projectId?c=n.projectId:s==="PROJECT_ID_API_KEY"&&n.keyId?c=n.keyId:s==="PROJECT_ID_API_SECRET"&&n.keySecret?(c=n.keySecret,l=!0):s==="VOICE_APPLICATION_KEY"&&n.applicationKey?c=n.applicationKey:s==="VOICE_APPLICATION_SECRET"&&n.applicationSecret&&(c=n.applicationSecret,l=!0)),c&&(e[s]={Value:c,Secret:l})}else e[s]={Value:String(a),Secret:!1}}}catch(r){t.debug("Could not read appsettings.json: "+r.message)}}else{let i=we.default.join(process.cwd(),".env");if(await X.default.pathExists(i))try{let r=await X.default.readFile(i,"utf8"),s={};r.split(`
44
- `).forEach(a=>{if(a.trim()&&!a.trim().startsWith("#")){let[c,...l]=a.split("=");c&&(s[c.trim()]=l.join("=").trim())}});for(let[a,c]of Object.entries(s))if(c===""||c===null||c===void 0){let l="",u=!1;n&&(a==="PROJECT_ID"&&n.projectId?l=n.projectId:a==="PROJECT_ID_API_KEY"&&n.keyId?l=n.keyId:a==="PROJECT_ID_API_SECRET"&&n.keySecret?(l=n.keySecret,u=!0):a==="VOICE_APPLICATION_KEY"&&n.applicationKey?l=n.applicationKey:a==="VOICE_APPLICATION_SECRET"&&n.applicationSecret&&(l=n.applicationSecret,u=!0)),l&&(e[a]={Value:l,Secret:u})}else e[a]={Value:c,Secret:!1}}catch(r){t.debug("Could not read .env file: "+r.message)}}return e}async function go(o,e){let i=Date.now(),r=!1,s;return t.newline(),d.start("\u23F3 Connecting to deployment stream..."),new Promise((a,c)=>{let l,u;t.debug(`Attempting to connect to SSE stream for function ${e}`),o.streamDeployment(e,g=>{t.debug(`SSE event received: ${g.type}`);let h=Math.floor((Date.now()-i)/1e3);switch(g.type){case"connected":d.text="\u23F3 Deployment stream connected, waiting for updates...";break;case"status":let S=g.data.data.message;d.text=`\u23F3 ${S} (${h}s)`;break;case"progress":let w=g.data.data.message,T=g.data.data.percentComplete;T?d.text=`\u23F3 ${w} (${T}%, ${h}s)`:d.text=`\u23F3 ${w} (${h}s)`;break;case"completed":r=!0,s=g.data.data.url,d.succeed("\u2705 Function deployed successfully"),o.getFunction(e).then(async $=>{if(t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${v.default.cyan($.name)}`),t.info(` Status: ${ut("Running")}`),t.info(` URL: ${v.default.blue(s)}`),s){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{d.start("Updating Sinch Voice callback URL..."),await st(s),d.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${v.default.cyan(s)}`)}catch(C){d.fail("Failed to update callback URL automatically"),t.warn(` Error: ${C.message}`),t.info(` Manual setup: ${v.default.cyan(`sinch voice callback-url ${s}`)}`)}t.info(` Test function: ${v.default.cyan(`curl ${s}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${v.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${v.default.cyan(`sinch functions status ${e}`)}`),l&&l(),u&&clearTimeout(u),a()}).catch($=>{t.error(`Failed to get function details: ${$.message}`),l&&l(),u&&clearTimeout(u),a()});break;case"failed":r=!0;let q=g.data.data.errorMessage;d.fail("\u274C Deployment failed"),t.newline(),t.error("Deployment failed:"),q&&t.error(` ${q}`),t.newline(),t.info("\u{1F4A1} Troubleshooting:"),t.info(` \u2022 Check logs: ${v.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${v.default.cyan(`sinch functions status ${e}`)}`),l&&l(),u&&clearTimeout(u),process.exit(1);break}},g=>{t.debug("SSE stream error, falling back to polling:",g),console.error("SSE Error details:",g),d.text="\u23F3 Deployment stream unavailable, checking status...",l&&l(),Jt(o,e,i,3e5).then(a).catch(c)}).then(g=>{t.debug("SSE stream setup successful, cleanup function received"),l=g,u=setTimeout(()=>{r||(d.fail("\u23F0 Deployment timeout"),t.newline(),t.warn("Deployment is taking longer than expected"),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${v.default.cyan(`sinch functions status ${e}`)}`),l&&l(),a())},3e5)}).catch(g=>{t.debug(`Failed to set up SSE stream, falling back to polling: ${g.message}`),Jt(o,e,i,3e5).then(a).catch(c)})})}async function Jt(o,e,n,i){for(;Date.now()-n<i;){try{let a=(await o.getFunctionStatus(e)).function;if(a.status==="Running"){if(d.succeed("\u2705 Function deployed successfully"),t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${v.default.cyan(a.name)}`),t.info(` Status: ${ut(a.status)}`),t.info(` URL: ${v.default.blue(a.containerAppUrl)}`),a.containerAppUrl){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{d.start("Updating Sinch Voice callback URL..."),await st(a.containerAppUrl),d.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${v.default.cyan(a.containerAppUrl)}`)}catch(l){d.fail("Failed to update callback URL automatically"),t.warn(` Error: ${l.message}`),t.info(` Manual setup: ${v.default.cyan(`sinch voice callback-url ${a.containerAppUrl}`)}`)}t.info(` Test function: ${v.default.cyan(`curl ${a.containerAppUrl}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${v.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${v.default.cyan(`sinch functions status ${e}`)}`);return}a.status==="Failed"&&(d.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: ${v.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${v.default.cyan(`sinch functions status ${e}`)}`),process.exit(1));let c=Math.floor((Date.now()-n)/1e3);d.text=`\u23F3 Deploying function... (${a.status}, ${c}s)`}catch(s){t.debug(`Status check failed: ${s.message}`)}await new Promise(s=>setTimeout(s,3e3))}d.fail("\u23F0 Deployment timeout"),t.newline(),t.warn("Deployment is taking longer than expected"),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${v.default.cyan(`sinch functions status ${e}`)}`)}function ut(o){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")}[o]||v.default.gray(o)}async function mo(o,e){let n=!1;if(e.nonInteractive)t.info("Generating documentation (non-interactive mode)"),n=!0;else{if(o.docsPreference==="never")return;if(ho(o))n=!0;else{let i=await Yt.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,p.set("docsPreference","always",!0),await p.saveProjectConfig()):i.docsChoice==="never"&&(n=!1,p.set("docsPreference","never",!0),await p.saveProjectConfig())}}if(n)try{d.start("\u{1F4DD} Generating documentation...");let{generateDocsFromLocal:i,saveDocumentationToFile:r}=(lt(),O(Mt)),s=await i(),a=we.default.basename(process.cwd());await r(s,"README.md",a),d.succeed("\u{1F4DD} Documentation updated in README.md")}catch(i){d.warn(`\u26A0\uFE0F Failed to generate documentation: ${i.message}`),t.warn("Continuing with deployment...")}}function ho(o){return o.docsPreference==="always"}Zt.exports=Qt});var rn=N((zi,on)=>{"use strict";var _=m(require("fs-extra")),ne=m(require("path")),be=m(require("chalk")),dt=require("child_process"),en=m(require("chokidar")),tn=require("commander"),He=m(require("inquirer"));I();K();j();var nn=new tn.Command("dev");nn.description("Start local development server").option("-p, --port <port>","Port to run on","3000").option("--no-watch","Disable file watching").option("-d, --debug","Enable debugging with --inspect").option("--tunnel","Force ngrok tunnel creation").option("--no-tunnel",'Disable ngrok tunnel and reset "always" preference').action(async o=>{try{if(await p.load(),!p.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=p.getProjectConfig();if(!e)throw new Error("No project configuration found");if((e.runtime||"node")==="csharp"){if((await _.default.readdir(process.cwd()).then(r=>r.filter(s=>s.endsWith(".csproj")))).length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.")}else{let i=ne.default.join(process.cwd(),"host.js");if(!await _.default.pathExists(i))throw new Error("host.js not found. Make sure you're in a valid Node.js function directory.")}t.title(`Starting ${e.name} (${e.runtime})`),t.info(`Port: ${o.port}`),t.info(`Watch: ${o.watch?"enabled":"disabled"}`),o.debug&&t.info("Debug: enabled on port 9229"),t.newline(),await yo(o,e)}catch(e){d.stop(),t.error(`Failed to start development server: ${e.message}`),process.exit(1)}});async function yo(o,e){let n=e.runtime||"node",i=null,r=!1;if(o.tunnel)r=!0;else if(o.noTunnel)r=!1,e.tunnel?.preference==="always"&&(p.set("tunnel",{...e.tunnel,preference:"no"},!0),await p.saveProjectConfig());else if(e.tunnel?.preference==="never")r=!1;else if(vo(e))r=!0;else{let{tunnelChoice:u}=await He.default.prompt([{type:"list",name:"tunnelChoice",message:"Create ngrok tunnel for external access?",choices:[{name:"Yes - Create tunnel this time",value:"yes"},{name:"No - Local only this time",value:"no"},{name:"Always - Create tunnel and remember preference",value:"always"},{name:"Never - Don't create tunnel and remember preference",value:"never"}],default:"no"}]);u==="yes"?r=!0:u==="no"?r=!1:u==="always"?(r=!0,p.set("tunnel",{...e.tunnel,preference:"always"},!0),await p.saveProjectConfig()):u==="never"&&(r=!1,p.set("tunnel",{...e.tunnel,preference:"never"},!0),await p.saveProjectConfig())}r&&(i=await $o(o.port,e));let s={...process.env,PORT:o.port,NODE_ENV:"development",SINCH_FUNCTIONS_LOCAL:"true"};e.variables&&Object.entries(e.variables).forEach(([u,g])=>{s[u]=g});try{let u=await p.getApplicationCredentials(e.voiceAppKey);u?(s.SINCH_APPLICATION_KEY=u.applicationKey,s.SINCH_APPLICATION_SECRET=u.applicationSecret,t.debug("\u2705 Injected application credentials for voice operations")):t.debug("\u26A0\uFE0F No application credentials found - voice features may not work")}catch(u){t.debug(`\u26A0\uFE0F Could not load application credentials: ${u.message}`)}t.info("\u{1F680} Starting local server...");let a=null,c=!1;function l(){if(a&&a.kill(),n==="csharp"){let u=["run"];o.port&&u.push("--urls",`http://localhost:${o.port}`),o.debug&&(s.ASPNETCORE_ENVIRONMENT="Development",s.ASPNETCORE_URLS=`http://localhost:${o.port}`),a=(0,dt.spawn)("dotnet",u,{env:s,stdio:"inherit",cwd:process.cwd()})}else{let u=ne.default.join(process.cwd(),"host.js"),g=[];o.debug&&g.push("--inspect=9229"),g.push(u),a=(0,dt.spawn)("node",g,{env:s,stdio:"inherit",cwd:process.cwd()})}a.on("spawn",async()=>{c||(c=!0,t.newline(),t.success(`\u2705 Server running on http://localhost:${o.port}`),o.debug&&(t.newline(),n==="csharp"?Po():bo()),t.newline(),t.info("\u{1F4A1} Development commands:"),t.info(` \u2022 Test function: ${be.default.cyan(`curl http://localhost:${o.port}`)}`),t.info(` \u2022 View in browser: ${be.default.cyan(`http://localhost:${o.port}`)}`),i&&t.info(` \u2022 Tunnel URL: ${be.default.cyan(i)}`),t.info(` \u2022 Stop server: ${be.default.gray("Ctrl+C")}`),o.watch&&t.info(` \u2022 File watching: ${be.default.green("enabled")}`))}),a.on("error",u=>{t.error(`Server error: ${u.message}`)}),a.on("exit",(u,g)=>{g!=="SIGTERM"&&g!=="SIGKILL"&&t.error(`Server exited with code ${u}`)})}l(),o.watch&&wo(()=>{t.info("\u{1F4DD} Files changed, restarting server..."),l()},n),process.on("SIGINT",()=>{t.newline(),t.info("\u{1F534} Stopping development server..."),a&&a.kill("SIGTERM"),process.exit(0)}),await new Promise(()=>{})}function wo(o,e="node"){let n=[".git/**",".DS_Store","*.tmp",".sinch-tmp/**"];e==="csharp"?n.push("bin/**","obj/**","*.user",".vs/**"):n.push("node_modules/**");let i=en.default.watch(".",{ignored:n,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:10}});i.on("change",r=>{t.debug(`File changed: ${r}`),o()}),i.on("add",r=>{t.debug(`File added: ${r}`),o()}),i.on("unlink",r=>{t.debug(`File removed: ${r}`),o()})}async function bo(){try{let o=await Ie("code",".vscode"),e=await Ie("cursor",".cursor"),n=await Ie("webstorm",".idea");if(o||e){let i=o?"VS Code":"Cursor",r=".vscode";if(t.info(`\u{1F41B} ${i} detected! Debug setup:`),await So(r))t.info(" 1. \u2705 Created .vscode/launch.json for you");else{let a=ne.default.join(process.cwd(),r,"launch.json");await _.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 Ie(o,e){try{if(o==="code"&&Co())return!0;let{spawn:n}=require("child_process"),i=await new Promise(s=>{let a=n(o,["--version"],{stdio:"pipe"});a.on("close",c=>s(c===0)),a.on("error",()=>s(!1))}),r=e?await _.default.pathExists(e):!1;return i||r}catch{return!1}}function Co(){return process.env.TERM_PROGRAM==="vscode"||!!process.env.VSCODE_IPC_HOOK||!!process.env.VSCODE_PID}async function So(o=".vscode"){try{let e=ne.default.join(process.cwd(),o),n=ne.default.join(e,"launch.json");if(await _.default.pathExists(n))return!1;await _.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 _.default.writeJson(n,i,{spaces:2}),!!await _.default.pathExists(n)}catch{return!1}}function vo(o){return o.tunnel?o.tunnel.preference==="always":!1}async function $o(o,e){try{let n=require("ngrok");await ko(),t.info("\u{1F310} Starting ngrok tunnel...");let i={port:o};e.tunnel&&e.tunnel.subdomain&&(i.subdomain=e.tunnel.subdomain);let r=await n.connect(i);t.success(`\u{1F310} Tunnel created: ${be.default.blue(r)}`);let s=e.tunnel?.preference||"no";return p.set("tunnel",{preference:s,lastUpdated:new Date().toISOString(),subdomain:i.subdomain||r.split("//")[1]?.split(".")[0],lastUrl:r},!0),await p.saveProjectConfig(),r}catch(n){return t.warn(`Failed to create tunnel: ${n.message}`),t.info("\u{1F4A1} You can still test locally on http://localhost:"+o),null}}async function ko(){if(p.get("ngrokAuthToken"))return;let e=p.getProjectConfig();if(e&&e.ngrokAuthPrompted)return;t.newline(),t.info("\u{1F510} Ngrok authentication enables:"),t.info(" \u2022 Persistent subdomain URLs"),t.info(" \u2022 Longer tunnel sessions"),t.info(" \u2022 Custom subdomains (with paid plan)"),t.newline();let{setupAuth:n}=await He.default.prompt([{type:"confirm",name:"setupAuth",message:"Would you like to add your ngrok auth token for persistent URLs?",default:!0}]);if(n){t.info("Get your free auth token at: https://dashboard.ngrok.com/get-started/your-authtoken"),t.newline();let{authToken:i}=await He.default.prompt([{type:"input",name:"authToken",message:"Enter your ngrok auth token:",validate:r=>!r||r.trim().length<10?"Please enter a valid ngrok auth token":!0}]);try{await require("ngrok").authtoken(i.trim()),p.set("ngrokAuthToken",i.trim()),await p.save(),t.success("\u2705 Ngrok authentication configured")}catch(r){t.error(`Failed to configure ngrok auth: ${r.message}`)}}else p.set("ngrokAuthPrompted",!0,!0),await p.saveProjectConfig(),t.info("\u{1F4A1} You can configure ngrok auth later with: sinch tunnel setup")}async function Po(){try{let o=await Ie("code",".vscode"),e=await Ie("devenv"),n=await Ie("rider",".idea");o?(t.info("\u{1F41B} VS Code detected! Debug setup:"),await Ao(".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 Ao(o=".vscode"){try{let e=ne.default.join(process.cwd(),o),n=ne.default.join(e,"launch.json");if(await _.default.pathExists(n))return!1;await _.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 _.default.writeJson(n,i,{spaces:2});let r=ne.default.join(e,"tasks.json");if(!await _.default.pathExists(r)){let s={version:"2.0.0",tasks:[{label:"build",command:"dotnet",type:"process",args:["build","${workspaceFolder}/Function.csproj","/property:GenerateFullPaths=true","/consoleloggerparameters:NoSummary"],problemMatcher:"$msCompile"}]};await _.default.writeJson(r,s,{spaces:2})}return await _.default.pathExists(n)}catch{return!1}}on.exports=nn});var un=N((tr,ln)=>{"use strict";var V=m(require("chalk")),sn=require("commander");L();I();K();j();var an=new sn.Command("status");an.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(o,e)=>{try{await p.load();let n=new A(p.getApiConfig()),i=o;if(!i){if(!p.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");if(i=p.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 Io(n,i):await Eo(n,i,e)}catch(n){d.stop(),t.error(`Failed to get function status: ${n.message}`),process.exit(1)}});async function Eo(o,e,n){d.start("\u{1F4E1} Loading function status...");try{let i=await o.getFunctionStatus(e);if(d.stop(),n.json){console.log(JSON.stringify(i,null,2));return}let r=i.function,s=i.runtimeStatus;t.newline(),t.title(`Function Status: ${r.name}`),t.newline(),t.info("\u{1F4CB} Function Details:"),t.info(` ID: ${V.default.gray(r.id)}`),t.info(` Name: ${V.default.cyan(r.name)}`),t.info(` Runtime: ${V.default.yellow(r.runtime)}`),t.info(` Status: ${cn(r.status)}`),t.info(` Created: ${new Date(r.createdAt).toLocaleString()}`),t.info(` Updated: ${new Date(r.updatedAt).toLocaleString()}`),r.containerAppUrl&&t.info(` URL: ${V.default.blue(r.containerAppUrl)}`),r.status==="Failed"&&r.errorMessage&&(t.newline(),t.error("Error Details:"),t.error(` ${r.errorMessage}`)),s&&(t.newline(),t.info("\u2699\uFE0F Runtime Status:"),t.info(` Replicas: ${s.readyReplicas}/${s.replicas}`),t.info(` CPU: ${s.cpu}`),t.info(` Memory: ${s.memory}`),s.lastActivity&&t.info(` Last Activity: ${new Date(s.lastActivity).toLocaleString()}`)),i.deployment&&(t.newline(),t.info("\u{1F680} Deployment Info:"),t.info(` Version: ${i.deployment.version}`),t.info(` Deployed: ${new Date(i.deployment.deployedAt).toLocaleString()}`),t.info(` Deployed By: ${i.deployment.deployedBy}`)),t.newline(),t.info("\u{1F4A1} Commands:"),t.info(` \u2022 View logs: ${V.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Redeploy: ${V.default.cyan("sinch functions deploy")}`),t.info(` \u2022 Delete: ${V.default.cyan(`sinch functions delete ${e}`)}`)}catch(i){throw d.stop(),i}}async function Io(o,e){t.info("\u{1F440} Watching function status (press Ctrl+C to stop)..."),t.newline();let n=null,i=setInterval(async()=>{try{let r=await o.getFunctionStatus(e),s=r.function.status;if(s!==n){let a=new Date().toLocaleTimeString();t.info(`[${a}] Status: ${cn(s)}`),n=s,s==="Running"?(t.success("Function is now running!"),r.function.containerAppUrl&&t.info(`URL: ${V.default.blue(r.function.containerAppUrl)}`)):s==="Failed"&&(t.error("Function deployment failed!"),r.function.errorMessage&&t.error(`Error: ${r.function.errorMessage}`),clearInterval(i))}}catch(r){t.error(`Error checking status: ${r.message}`)}},3e3);process.on("SIGINT",()=>{clearInterval(i),t.newline(),t.info("Stopped watching function status"),process.exit(0)})}function cn(o){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")}[o]||V.default.gray(o)}ln.exports=an});var bn=N((sr,wn)=>{"use strict";var Ce=m(require("chalk")),fn=require("commander");L();I();K();j();var pt=require("child_process"),xe=m(require("fs")),_e=m(require("os")),Ne=m(require("path")),ft=new fn.Command("logs");ft.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(o,e)=>{try{await p.load();let n=new A(p.getApiConfig()),i=o;if(!i){if(!p.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let s=p.getProjectConfig();if(!s)throw new Error("No project configuration found");if(i=s.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}d.start("Loading function details...");let r=await n.getFunction(i);d.stop(),t.info(`\u{1F4CB} Logs for function: ${Ce.default.cyan(r.name)} (${To(r.status)})`),t.newline(),e.follow?await gn(n,i,r.name,e):await Ko(n,i,e)}catch(n){d.stop(),t.error(`Failed to get logs: ${n.message}`),process.exit(1)}});ft.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(o,e)=>{try{await p.load();let n=new A(p.getApiConfig()),i=o;if(!i){if(!p.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let s=p.getProjectConfig();if(!s)throw new Error("No project configuration found");if(i=s.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}d.start("Connecting to log stream...");let r=await Ro(n,i);d.stop(),await gn(n,i,r.name,{...e,follow:!0})}catch(n){d.stop(),t.error(`Failed to stream logs: ${n.message}`),process.exit(1)}});async function Ro(o,e){return await o.getFunction(e)}async function gn(o,e,n,i){let r=o.baseUrl.replace(/\/+$/,""),s=o.projectId,a=`${r}/v1/projects/${s}/functions/${e}/logs/stream`,c=o.credentials,l=[],u=hn(l,"STREAMING",n),g={Accept:"text/event-stream","Cache-Control":"no-cache"};if(c)try{let S=await c.retrieve();if(S&&S.keyId&&S.keySecret){let w=Buffer.from(`${S.keyId}:${S.keySecret}`).toString("base64");g.Authorization=`Basic ${w}`}}catch(S){t.debug("Failed to add authentication:",S)}let h=new AbortController;try{let S=await fetch(a,{method:"GET",headers:g,signal:h.signal});if(!S.ok)throw new Error(`SSE connection failed: ${S.status} ${S.statusText}`);if(!S.body)throw new Error("Response body is null");dn(u.statusBar,"CONNECTED",n),u.screen.render();let w=S.body.getReader(),T=new TextDecoder,q="";(async()=>{try{for(;;){let{done:C,value:b}=await w.read();if(C)break;q+=T.decode(b,{stream:!0});let y=q.split(`
45
- `);q=y.pop()||"";for(let P of y)if(!P.startsWith("event:")&&P.startsWith("data:")){let Q=P.substring(5).trim();if(Q)try{let E=JSON.parse(Q);l.push(E),mn(u.table,E,l),u.table.focus(),u.screen.render()}catch{}}}}catch(C){C.name!=="AbortError"&&(dn(u.statusBar,"RECONNECTING",n),u.screen.render())}})(),u.screen.key(["q","C-c"],()=>{h.abort(),process.exit(0)}),await new Promise(()=>{})}catch(S){h.abort(),t.error(`\u274C Streaming failed: ${S.message}`),process.exit(1)}}function To(o){return{Running:Ce.default.green("\u2705 Running"),Failed:Ce.default.red("\u274C Failed"),Pending:Ce.default.yellow("\u23F3 Pending"),Building:Ce.default.blue("\u{1F528} Building")}[o]||Ce.default.gray(o)}var Se=[];function mn(o,e,n){let i=new Date(e.startTime),r=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"),s=Uo(e),a=`${e.executionTimeMs}ms`,c=e.statusCode.toString(),l=process.stdout.columns||120,g=Math.max(30,l-35),h=e.url.length>g?e.url.substring(0,g-2)+"..":e.url;Se.push([r,s,a,c,h]),Se.length>100&&(Se=Se.slice(-100),n&&n.length>100&&n.splice(0,n.length-100));let S=[["Time","Callback","Duration","Status","Path"],...Se];o.setData(S)}function Do(o,e,n,i,r){try{let s=require("blessed");t.debug(`Showing request details for ${o.httpMethod} ${o.url}`);let a=s.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 "}),c=s.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"}});s.box({parent:a,top:2,left:2,width:"100%-4",height:1,content:`{bold}{cyan-fg}${o.httpMethod}{/} {blue-fg}${o.url}{/} - {${_o(o.statusCode)}}${o.statusCode}{/} - {yellow-fg}${o.executionTimeMs}ms{/} - {magenta-fg}${o.memoryUsedMB||0}MB{/}`,tags:!0,style:{bg:"black"}});let l=s.box({parent:a,top:4,left:2,width:"100%-4",height:"100%-5",scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,content:jo(o)});l.focus(),e.render();let u=!0,g=()=>{u&&(u=!1,a.destroy(),n.focus(),e.render())};e.key(["escape","q"],()=>{u&&g()}),e.key(["up","k"],()=>{u&&(l.scroll(-1),e.render())}),e.key(["down","j"],()=>{u&&(l.scroll(1),e.render())}),e.on("keypress",(h,S)=>{u&&t.debug(`Key pressed: ch="${h}" key=${JSON.stringify(S)}`)}),e.key(["J","j"],()=>{u&&(t.debug("J/j key pressed - attempting JSON copy"),c.setContent("{black-bg}{yellow-fg} J KEY PRESSED - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let h=JSON.stringify(o,null,2);t.debug(`JSON content length: ${h.length}`),t.debug("Attempting native clipboard copy"),Ge(h).then(()=>{c.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded"),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(S=>{t.debug(`Native clipboard failed: ${S.message}`);let w=Ne.default.join(_e.default.tmpdir(),`sinch-request-${Date.now()}.json`);xe.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 JSON saved to: ${w}{/}`),t.debug(`Saved to temp file: ${w}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(h){t.debug(`JSON copy error: ${h.message}`),c.setContent(`{red-fg}\u2717 Copy failed: ${h.message}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["C","c"],()=>{u&&(t.debug("C/c key pressed - attempting cURL copy"),c.setContent("{black-bg}{yellow-fg} C KEY PRESSED - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let h=pn(o);t.debug("Attempting native clipboard copy for cURL"),Ge(h).then(()=>{c.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded for cURL"),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(S=>{t.debug(`Native clipboard failed for cURL: ${S.message}`);let w=Ne.default.join(_e.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);xe.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 cURL saved to: ${w}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(h){t.debug(`cURL copy error: ${h.message}`),c.setContent(`{red-fg}\u2717 Copy failed: ${h.message}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["1"],()=>{u&&(t.debug("1 key pressed - copying JSON (alternative binding)"),c.setContent("{black-bg}{yellow-fg} 1 KEY - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let h=JSON.stringify(o,null,2);Ge(h).then(()=>{c.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(S=>{let w=Ne.default.join(_e.default.tmpdir(),`sinch-request-${Date.now()}.json`);xe.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 JSON saved to: ${w}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(h){c.setContent(`{red-fg}\u2717 Copy failed: ${h.message}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["2"],()=>{u&&(t.debug("2 key pressed - copying cURL (alternative binding)"),c.setContent("{black-bg}{yellow-fg} 2 KEY - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let h=pn(o);Ge(h).then(()=>{c.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(S=>{let w=Ne.default.join(_e.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);xe.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 cURL saved to: ${w}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(h){c.setContent(`{red-fg}\u2717 Copy failed: ${h.message}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))})}catch(s){t.debug(`Error in showBlessedZoomedRequest: ${s.message}`)}}function jo(o){let e="";return e+=`
46
- `,e+=Fo(o),e+=`
47
- `,e+=Oo(o),e+=`
48
- `,e+=Lo(o),e}function Fo(o){let e="",n=process.stdout.columns-6;e+="{bold}{green-fg}\u250C\u2500 REQUEST "+"\u2500".repeat(Math.max(0,n-10))+`\u2510{/}
49
- `;let i=No(o);if(i&&(e+=`{green-fg}\u2502{/} {bold}Call ID:{/} {cyan-fg}${i}{/}
43
+ `),e}async function st(o,e){let n=se.resolve(e);await Ee.writeFile(n,o,"utf8")}function Kt(o){switch(se.extname(o).toLowerCase()){case".js":return"node";case".py":return"python";case".cs":return"csharp";default:return"node"}}var Ee,se,at=de(()=>{"use strict";Ee=m(require("fs-extra")),se=m(require("path"));_();A()});var Qt=N((Vi,zt)=>{"use strict";var X=m(require("fs-extra")),me=m(require("path")),v=m(require("chalk")),Jt=require("commander");_();A();B();F();Nt();var Mt=m(require("adm-zip")),Wt=m(require("os")),Ht=m(require("inquirer")),Gt=require("child_process"),Yt=new Jt.Command("deploy");Yt.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").action(async o=>{try{if(await p.load(),!p.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=p.getProjectConfig(),n=o.name||e.name,i=e.runtime;await po(e,o),d.start("\u{1F4E6} Packaging function...");let r=await co(n);d.succeed("\u{1F4E6} Function packaged"),d.start("\u{1F527} Preparing configuration...");let s=await lo(i);d.succeed("\u{1F527} Configuration prepared"),d.start("\u{1F680} Submitting deployment...");let a=new E(p.getApiConfig()),c=await X.default.readFile(r),l=await a.deployFunction(n,i,c,s);if(await X.default.remove(r),d.succeed("\u{1F680} Deployment submitted"),p.set("functionId",l.id,!0),await p.saveProjectConfig(),t.newline(),t.info(`Function ID: ${v.default.cyan(l.id)}`),t.info(`Status: ${ct(l.status)}`),o.wait===!1){t.newline(),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${v.default.cyan(`sinch functions status ${l.id}`)}`);return}await uo(a,l.id)}catch(e){d.stop(),t.error(`Failed to deploy function: ${e.message}`),process.exit(1)}});async function co(o){let e=new Mt.default,n=process.cwd(),i=me.default.join(Wt.default.tmpdir(),`${o}-${Date.now()}.zip`),r=["node_modules","bin","obj",".git",".DS_Store","*.zip",".env",".env.local","npm-debug.log*",".sinch-tmp","examples","claude.md","readme.md"];async function s(a,c=""){let l=await X.default.readdir(a);for(let u of l){let g=me.default.join(a,u),h=me.default.join(c,u).replace(/\\/g,"/");if(r.some(w=>u.match(new RegExp(w.replace("*",".*")))))continue;if((await X.default.stat(g)).isDirectory())await s(g,h);else{let w=await X.default.readFile(g);e.addFile(h,w)}}}return await s(n),e.writeZip(i),i}async function lo(o){let e={},n=null;try{n=await p.getCredentials()}catch(i){t.debug("Could not load credentials from secure storage: "+i.message)}if(o==="csharp"){let i=me.default.join(process.cwd(),"appsettings.json");if(await X.default.pathExists(i))try{let r=await X.default.readJson(i);for(let s of Object.keys(r)){if(s==="Logging"||s==="AllowedHosts")continue;let a=r[s];if(a===""||a===null||a===void 0){let c="",l=!1;try{let u=(0,Gt.execSync)(`dotnet user-secrets get "${s}"`,{cwd:process.cwd(),encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim();u&&!u.includes("No secrets configured")&&!u.includes("was not found")&&(c=u,l=!0,t.debug(`Found ${s} in dotnet user-secrets`))}catch{}!c&&n&&(s==="PROJECT_ID"&&n.projectId?c=n.projectId:s==="PROJECT_ID_API_KEY"&&n.keyId?c=n.keyId:s==="PROJECT_ID_API_SECRET"&&n.keySecret?(c=n.keySecret,l=!0):s==="VOICE_APPLICATION_KEY"&&n.applicationKey?c=n.applicationKey:s==="VOICE_APPLICATION_SECRET"&&n.applicationSecret&&(c=n.applicationSecret,l=!0)),c&&(e[s]={Value:c,Secret:l})}else e[s]={Value:String(a),Secret:!1}}}catch(r){t.debug("Could not read appsettings.json: "+r.message)}}else{let i=me.default.join(process.cwd(),".env");if(await X.default.pathExists(i))try{let r=await X.default.readFile(i,"utf8"),s={};r.split(`
44
+ `).forEach(a=>{if(a.trim()&&!a.trim().startsWith("#")){let[c,...l]=a.split("=");c&&(s[c.trim()]=l.join("=").trim())}});for(let[a,c]of Object.entries(s))if(c===""||c===null||c===void 0){let l="",u=!1;n&&(a==="PROJECT_ID"&&n.projectId?l=n.projectId:a==="PROJECT_ID_API_KEY"&&n.keyId?l=n.keyId:a==="PROJECT_ID_API_SECRET"&&n.keySecret?(l=n.keySecret,u=!0):a==="VOICE_APPLICATION_KEY"&&n.applicationKey?l=n.applicationKey:a==="VOICE_APPLICATION_SECRET"&&n.applicationSecret&&(l=n.applicationSecret,u=!0)),l&&(e[a]={Value:l,Secret:u})}else e[a]={Value:c,Secret:!1}}catch(r){t.debug("Could not read .env file: "+r.message)}}return e}async function uo(o,e){let i=Date.now(),r=!1,s;return t.newline(),d.start("\u23F3 Connecting to deployment stream..."),new Promise((a,c)=>{let l,u;t.debug(`Attempting to connect to SSE stream for function ${e}`),o.streamDeployment(e,g=>{t.debug(`SSE event received: ${g.type}`);let h=Math.floor((Date.now()-i)/1e3);switch(g.type){case"connected":d.text="\u23F3 Deployment stream connected, waiting for updates...";break;case"status":let S=g.data.data.message;d.text=`\u23F3 ${S} (${h}s)`;break;case"progress":let w=g.data.data.message,T=g.data.data.percentComplete;T?d.text=`\u23F3 ${w} (${T}%, ${h}s)`:d.text=`\u23F3 ${w} (${h}s)`;break;case"completed":r=!0,s=g.data.data.url,d.succeed("\u2705 Function deployed successfully"),o.getFunction(e).then(async $=>{if(t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${v.default.cyan($.name)}`),t.info(` Status: ${ct("Running")}`),t.info(` URL: ${v.default.blue(s)}`),s){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{d.start("Updating Sinch Voice callback URL..."),await it(s),d.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${v.default.cyan(s)}`)}catch(b){d.fail("Failed to update callback URL automatically"),t.warn(` Error: ${b.message}`),t.info(` Manual setup: ${v.default.cyan(`sinch voice callback-url ${s}`)}`)}t.info(` Test function: ${v.default.cyan(`curl ${s}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${v.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${v.default.cyan(`sinch functions status ${e}`)}`),l&&l(),u&&clearTimeout(u),a()}).catch($=>{t.error(`Failed to get function details: ${$.message}`),l&&l(),u&&clearTimeout(u),a()});break;case"failed":r=!0;let V=g.data.data.errorMessage;d.fail("\u274C Deployment failed"),t.newline(),t.error("Deployment failed:"),V&&t.error(` ${V}`),t.newline(),t.info("\u{1F4A1} Troubleshooting:"),t.info(` \u2022 Check logs: ${v.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${v.default.cyan(`sinch functions status ${e}`)}`),l&&l(),u&&clearTimeout(u),process.exit(1);break}},g=>{t.debug("SSE stream error, falling back to polling:",g),console.error("SSE Error details:",g),d.text="\u23F3 Deployment stream unavailable, checking status...",l&&l(),Vt(o,e,i,3e5).then(a).catch(c)}).then(g=>{t.debug("SSE stream setup successful, cleanup function received"),l=g,u=setTimeout(()=>{r||(d.fail("\u23F0 Deployment timeout"),t.newline(),t.warn("Deployment is taking longer than expected"),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${v.default.cyan(`sinch functions status ${e}`)}`),l&&l(),a())},3e5)}).catch(g=>{t.debug(`Failed to set up SSE stream, falling back to polling: ${g.message}`),Vt(o,e,i,3e5).then(a).catch(c)})})}async function Vt(o,e,n,i){for(;Date.now()-n<i;){try{let a=(await o.getFunctionStatus(e)).function;if(a.status==="Running"){if(d.succeed("\u2705 Function deployed successfully"),t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${v.default.cyan(a.name)}`),t.info(` Status: ${ct(a.status)}`),t.info(` URL: ${v.default.blue(a.containerAppUrl)}`),a.containerAppUrl){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{d.start("Updating Sinch Voice callback URL..."),await it(a.containerAppUrl),d.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${v.default.cyan(a.containerAppUrl)}`)}catch(l){d.fail("Failed to update callback URL automatically"),t.warn(` Error: ${l.message}`),t.info(` Manual setup: ${v.default.cyan(`sinch voice callback-url ${a.containerAppUrl}`)}`)}t.info(` Test function: ${v.default.cyan(`curl ${a.containerAppUrl}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${v.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${v.default.cyan(`sinch functions status ${e}`)}`);return}a.status==="Failed"&&(d.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: ${v.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${v.default.cyan(`sinch functions status ${e}`)}`),process.exit(1));let c=Math.floor((Date.now()-n)/1e3);d.text=`\u23F3 Deploying function... (${a.status}, ${c}s)`}catch(s){t.debug(`Status check failed: ${s.message}`)}await new Promise(s=>setTimeout(s,3e3))}d.fail("\u23F0 Deployment timeout"),t.newline(),t.warn("Deployment is taking longer than expected"),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${v.default.cyan(`sinch functions status ${e}`)}`)}function ct(o){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")}[o]||v.default.gray(o)}async function po(o,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(o.docsPreference==="never")return;if(fo(o))n=!0;else{let i=await Ht.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,p.set("docsPreference","always",!0),await p.saveProjectConfig()):i.docsChoice==="never"&&(n=!1,p.set("docsPreference","never",!0),await p.saveProjectConfig())}}if(n)try{d.start("\u{1F4DD} Generating documentation...");let{generateDocsFromLocal:i,saveDocumentationToFile:r}=(at(),D(qt)),s=await i(),a=me.default.basename(process.cwd());await r(s,"README.md",a),d.succeed("\u{1F4DD} Documentation updated in README.md")}catch(i){d.warn(`\u26A0\uFE0F Failed to generate documentation: ${i.message}`),t.warn("Continuing with deployment...")}}function fo(o){return o.docsPreference==="always"}zt.exports=Yt});var nn=N((Gi,tn)=>{"use strict";var L=m(require("fs-extra")),ne=m(require("path")),he=m(require("chalk")),lt=require("child_process"),Zt=m(require("chokidar")),Xt=require("commander"),Me=m(require("inquirer"));A();B();F();var en=new Xt.Command("dev");en.description("Start local development server").option("-p, --port <port>","Port to run on","3000").option("--no-watch","Disable file watching").option("-d, --debug","Enable debugging with --inspect").option("--tunnel","Force ngrok tunnel creation").option("--no-tunnel",'Disable ngrok tunnel and reset "always" preference').action(async o=>{try{if(await p.load(),!p.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=p.getProjectConfig();if(!e)throw new Error("No project configuration found");if((e.runtime||"node")==="csharp"){if((await L.default.readdir(process.cwd()).then(r=>r.filter(s=>s.endsWith(".csproj")))).length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.")}else{let i=ne.default.join(process.cwd(),"host.js");if(!await L.default.pathExists(i))throw new Error("host.js not found. Make sure you're in a valid Node.js function directory.")}t.title(`Starting ${e.name} (${e.runtime})`),t.info(`Port: ${o.port}`),t.info(`Watch: ${o.watch?"enabled":"disabled"}`),o.debug&&t.info("Debug: enabled on port 9229"),t.newline(),await go(o,e)}catch(e){d.stop(),t.error(`Failed to start development server: ${e.message}`),process.exit(1)}});async function go(o,e){let n=e.runtime||"node",i=null,r=!1;if(o.tunnel===!0)r=!0;else if(o.tunnel===!1)r=!1,e.tunnel?.preference==="always"&&(p.set("tunnel",{...e.tunnel,preference:"no"},!0),await p.saveProjectConfig());else if(e.tunnel?.preference==="never")r=!1;else if(Co(e))r=!0;else{let{tunnelChoice:u}=await Me.default.prompt([{type:"list",name:"tunnelChoice",message:"Create sinch tunnel for external access?",choices:[{name:"Yes - Create tunnel this time",value:"yes"},{name:"No - Local only this time",value:"no"},{name:"Always - Create tunnel and remember preference",value:"always"},{name:"Never - Don't create tunnel and remember preference",value:"never"}],default:"no"}]);u==="yes"?r=!0:u==="no"?r=!1:u==="always"?(r=!0,p.set("tunnel",{...e.tunnel,preference:"always"},!0),await p.saveProjectConfig()):u==="never"&&(r=!1,p.set("tunnel",{...e.tunnel,preference:"never"},!0),await p.saveProjectConfig())}r&&(i=await bo(o.port,e));let s={...process.env,PORT:o.port,NODE_ENV:"development",SINCH_FUNCTIONS_LOCAL:"true",SINCH_TUNNEL:r?"true":"false"};e.variables&&Object.entries(e.variables).forEach(([u,g])=>{s[u]=g});try{let u=await p.getApplicationCredentials(e.voiceAppKey);u?(s.SINCH_APPLICATION_KEY=u.applicationKey,s.SINCH_APPLICATION_SECRET=u.applicationSecret,t.debug("\u2705 Injected application credentials for voice operations")):t.debug("\u26A0\uFE0F No application credentials found - voice features may not work")}catch(u){t.debug(`\u26A0\uFE0F Could not load application credentials: ${u.message}`)}t.info("\u{1F680} Starting local server...");let a=null,c=!1;function l(){if(a&&a.kill(),n==="csharp"){let u=["run"];o.port&&u.push("--urls",`http://localhost:${o.port}`),o.debug&&(s.ASPNETCORE_ENVIRONMENT="Development",s.ASPNETCORE_URLS=`http://localhost:${o.port}`),a=(0,lt.spawn)("dotnet",u,{env:s,stdio:"inherit",cwd:process.cwd()})}else{let u=ne.default.join(process.cwd(),"host.js"),g=[];o.debug&&g.push("--inspect=9229"),g.push(u),a=(0,lt.spawn)("node",g,{env:s,stdio:"inherit",cwd:process.cwd()})}a.on("spawn",async()=>{c||(c=!0,t.newline(),t.success(`\u2705 Server running on http://localhost:${o.port}`),o.debug&&(t.newline(),n==="csharp"?vo():ho()),t.newline(),t.info("\u{1F4A1} Development commands:"),t.info(` \u2022 Test function: ${he.default.cyan(`curl http://localhost:${o.port}`)}`),t.info(` \u2022 View in browser: ${he.default.cyan(`http://localhost:${o.port}`)}`),i&&t.info(` \u2022 Tunnel URL: ${he.default.cyan(i)}`),t.info(` \u2022 Stop server: ${he.default.gray("Ctrl+C")}`),o.watch&&t.info(` \u2022 File watching: ${he.default.green("enabled")}`))}),a.on("error",u=>{t.error(`Server error: ${u.message}`)}),a.on("exit",(u,g)=>{g!=="SIGTERM"&&g!=="SIGKILL"&&t.error(`Server exited with code ${u}`)})}l(),o.watch&&mo(()=>{t.info("\u{1F4DD} Files changed, restarting server..."),l()},n),process.on("SIGINT",()=>{t.newline(),t.info("\u{1F534} Stopping development server..."),a&&a.kill("SIGTERM"),process.exit(0)}),await new Promise(()=>{})}function mo(o,e="node"){let n=[".git/**",".DS_Store","*.tmp",".sinch-tmp/**"];e==="csharp"?n.push("bin/**","obj/**","*.user",".vs/**"):n.push("node_modules/**");let i=Zt.default.watch(".",{ignored:n,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:10}});i.on("change",r=>{t.debug(`File changed: ${r}`),o()}),i.on("add",r=>{t.debug(`File added: ${r}`),o()}),i.on("unlink",r=>{t.debug(`File removed: ${r}`),o()})}async function ho(){try{let o=await Ie("code",".vscode"),e=await Ie("cursor",".cursor"),n=await Ie("webstorm",".idea");if(o||e){let i=o?"VS Code":"Cursor",r=".vscode";if(t.info(`\u{1F41B} ${i} detected! Debug setup:`),await wo(r))t.info(" 1. \u2705 Created .vscode/launch.json for you");else{let a=ne.default.join(process.cwd(),r,"launch.json");await L.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 Ie(o,e){try{if(o==="code"&&yo())return!0;let{spawn:n}=require("child_process"),i=await new Promise(s=>{let a=n(o,["--version"],{stdio:"pipe"});a.on("close",c=>s(c===0)),a.on("error",()=>s(!1))}),r=e?await L.default.pathExists(e):!1;return i||r}catch{return!1}}function yo(){return process.env.TERM_PROGRAM==="vscode"||!!process.env.VSCODE_IPC_HOOK||!!process.env.VSCODE_PID}async function wo(o=".vscode"){try{let e=ne.default.join(process.cwd(),o),n=ne.default.join(e,"launch.json");if(await L.default.pathExists(n))return!1;await L.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 L.default.writeJson(n,i,{spaces:2}),!!await L.default.pathExists(n)}catch{return!1}}function Co(o){return o.tunnel?o.tunnel.preference==="always":!1}async function bo(o,e){try{let n=require("ngrok");await So(),t.info("\u{1F310} Starting ngrok tunnel...");let i={port:o};e.tunnel&&e.tunnel.subdomain&&(i.subdomain=e.tunnel.subdomain);let r=await n.connect(i);t.success(`\u{1F310} Tunnel created: ${he.default.blue(r)}`);let s=e.tunnel?.preference||"no";return p.set("tunnel",{preference:s,lastUpdated:new Date().toISOString(),subdomain:i.subdomain||r.split("//")[1]?.split(".")[0],lastUrl:r},!0),await p.saveProjectConfig(),r}catch(n){return t.warn(`Failed to create tunnel: ${n.message}`),t.info("\u{1F4A1} You can still test locally on http://localhost:"+o),null}}async function So(){if(p.get("ngrokAuthToken"))return;let e=p.getProjectConfig();if(e&&e.ngrokAuthPrompted)return;t.newline(),t.info("\u{1F510} Ngrok authentication enables:"),t.info(" \u2022 Persistent subdomain URLs"),t.info(" \u2022 Longer tunnel sessions"),t.info(" \u2022 Custom subdomains (with paid plan)"),t.newline();let{setupAuth:n}=await Me.default.prompt([{type:"confirm",name:"setupAuth",message:"Would you like to add your ngrok auth token for persistent URLs?",default:!0}]);if(n){t.info("Get your free auth token at: https://dashboard.ngrok.com/get-started/your-authtoken"),t.newline();let{authToken:i}=await Me.default.prompt([{type:"input",name:"authToken",message:"Enter your ngrok auth token:",validate:r=>!r||r.trim().length<10?"Please enter a valid ngrok auth token":!0}]);try{await require("ngrok").authtoken(i.trim()),p.set("ngrokAuthToken",i.trim()),await p.save(),t.success("\u2705 Ngrok authentication configured")}catch(r){t.error(`Failed to configure ngrok auth: ${r.message}`)}}else p.set("ngrokAuthPrompted",!0,!0),await p.saveProjectConfig(),t.info("\u{1F4A1} You can configure ngrok auth later with: sinch tunnel setup")}async function vo(){try{let o=await Ie("code",".vscode"),e=await Ie("devenv"),n=await Ie("rider",".idea");o?(t.info("\u{1F41B} VS Code detected! Debug setup:"),await $o(".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 $o(o=".vscode"){try{let e=ne.default.join(process.cwd(),o),n=ne.default.join(e,"launch.json");if(await L.default.pathExists(n))return!1;await L.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 L.default.writeJson(n,i,{spaces:2});let r=ne.default.join(e,"tasks.json");if(!await L.default.pathExists(r)){let s={version:"2.0.0",tasks:[{label:"build",command:"dotnet",type:"process",args:["build","${workspaceFolder}/Function.csproj","/property:GenerateFullPaths=true","/consoleloggerparameters:NoSummary"],problemMatcher:"$msCompile"}]};await L.default.writeJson(r,s,{spaces:2})}return await L.default.pathExists(n)}catch{return!1}}tn.exports=en});var cn=N((Xi,an)=>{"use strict";var q=m(require("chalk")),on=require("commander");_();A();B();F();var rn=new on.Command("status");rn.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(o,e)=>{try{await p.load();let n=new E(p.getApiConfig()),i=o;if(!i){if(!p.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");if(i=p.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 Po(n,i):await ko(n,i,e)}catch(n){d.stop(),t.error(`Failed to get function status: ${n.message}`),process.exit(1)}});async function ko(o,e,n){d.start("\u{1F4E1} Loading function status...");try{let i=await o.getFunction(e),r=await o.getFunctionStatus(e);if(d.stop(),n.json){console.log(JSON.stringify({function:i,deployment:r},null,2));return}let s=i,a=r.status,c=r.error;t.newline(),t.title(`Function Status: ${s.name}`),t.newline(),t.info("\u{1F4CB} Function Details:"),t.info(` ID: ${q.default.gray(s.id)}`),t.info(` Name: ${q.default.cyan(s.name)}`),t.info(` Runtime: ${q.default.yellow(s.runtime)}`),t.info(` Deployment Status: ${sn(a)}`),s.created&&t.info(` Created: ${new Date(s.created).toLocaleString()}`),s.updated&&t.info(` Updated: ${new Date(s.updated).toLocaleString()}`),s.url&&t.info(` URL: ${q.default.blue(s.url)}`),a==="Failed"&&c&&(t.newline(),t.error("Deployment Error:"),t.error(` ${c}`)),t.newline(),t.info("\u{1F4A1} Commands:"),t.info(` \u2022 View logs: ${q.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Redeploy: ${q.default.cyan("sinch functions deploy")}`),t.info(` \u2022 Delete: ${q.default.cyan(`sinch functions delete ${e}`)}`)}catch(i){throw d.stop(),i}}async function Po(o,e){t.info("\u{1F440} Watching deployment status (press Ctrl+C to stop)..."),t.newline();let n=null,i=setInterval(async()=>{try{let r=await o.getFunctionStatus(e),s=r.status;if(s!==n){let a=new Date().toLocaleTimeString();if(t.info(`[${a}] Status: ${sn(s)}`),n=s,s==="Running"){t.success("Function deployment is now running!");try{let c=await o.getFunction(e);c.url&&t.info(`URL: ${q.default.blue(c.url)}`)}catch{}}else s==="Failed"&&(t.error("Function deployment failed!"),r.error&&t.error(`Error: ${r.error}`),clearInterval(i))}}catch(r){t.error(`Error checking status: ${r.message}`)}},3e3);process.on("SIGINT",()=>{clearInterval(i),t.newline(),t.info("Stopped watching function status"),process.exit(0)})}function sn(o){return{Running:q.default.green("\u2705 Running"),Failed:q.default.red("\u274C Failed"),Pending:q.default.yellow("\u23F3 Pending"),Building:q.default.blue("\u{1F528} Building")}[o]||q.default.gray(o)}an.exports=rn});var yn=N((ir,hn)=>{"use strict";var ye=m(require("chalk")),dn=require("commander");_();A();B();F();var ut=require("child_process"),Fe=m(require("fs")),Oe=m(require("os")),_e=m(require("path")),dt=new dn.Command("logs");dt.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(o,e)=>{try{await p.load();let n=new E(p.getApiConfig()),i=o;if(!i){if(!p.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let s=p.getProjectConfig();if(!s)throw new Error("No project configuration found");if(i=s.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}d.start("Loading function details...");let r=await n.getFunction(i);d.stop(),t.info(`\u{1F4CB} Logs for function: ${ye.default.cyan(r.name)} (${Io(r.status)})`),t.newline(),e.follow?await pn(n,i,r.name,e):await Lo(n,i,e)}catch(n){d.stop(),t.error(`Failed to get logs: ${n.message}`),process.exit(1)}});dt.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(o,e)=>{try{await p.load();let n=new E(p.getApiConfig()),i=o;if(!i){if(!p.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let s=p.getProjectConfig();if(!s)throw new Error("No project configuration found");if(i=s.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}d.start("Connecting to log stream...");let r=await Eo(n,i);d.stop(),await pn(n,i,r.name,{...e,follow:!0})}catch(n){d.stop(),t.error(`Failed to stream logs: ${n.message}`),process.exit(1)}});async function Eo(o,e){return await o.getFunction(e)}async function pn(o,e,n,i){let r=o.baseUrl.replace(/\/+$/,""),s=o.projectId,a=`${r}/v1/projects/${s}/functions/${e}/logs/stream`,c=o.credentials,l=[],u=gn(l,"STREAMING",n),g={Accept:"text/event-stream","Cache-Control":"no-cache"};if(c)try{let S=await c.retrieve();if(S&&S.keyId&&S.keySecret){let w=Buffer.from(`${S.keyId}:${S.keySecret}`).toString("base64");g.Authorization=`Basic ${w}`}}catch(S){t.debug("Failed to add authentication:",S)}let h=new AbortController;try{let S=await fetch(a,{method:"GET",headers:g,signal:h.signal});if(!S.ok)throw new Error(`SSE connection failed: ${S.status} ${S.statusText}`);if(!S.body)throw new Error("Response body is null");ln(u.statusBar,"CONNECTED",n),u.screen.render();let w=S.body.getReader(),T=new TextDecoder,V="";(async()=>{try{for(;;){let{done:b,value:C}=await w.read();if(b)break;V+=T.decode(C,{stream:!0});let y=V.split(`
45
+ `);V=y.pop()||"";for(let P of y)if(!P.startsWith("event:")&&P.startsWith("data:")){let Q=P.substring(5).trim();if(Q)try{let I=JSON.parse(Q);l.push(I),fn(u.table,I,l),u.table.focus(),u.screen.render()}catch{}}}}catch(b){b.name!=="AbortError"&&(ln(u.statusBar,"RECONNECTING",n),u.screen.render())}})(),u.screen.key(["q","C-c"],()=>{h.abort(),process.exit(0)}),await new Promise(()=>{})}catch(S){h.abort(),t.error(`\u274C Streaming failed: ${S.message}`),process.exit(1)}}function Io(o){return{Running:ye.default.green("\u2705 Running"),Failed:ye.default.red("\u274C Failed"),Pending:ye.default.yellow("\u23F3 Pending"),Building:ye.default.blue("\u{1F528} Building")}[o]||ye.default.gray(o)}var we=[];function fn(o,e,n){let i=new Date(e.startTime),r=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"),s=xo(e),a=`${e.executionTimeMs}ms`,c=e.statusCode.toString(),l=process.stdout.columns||120,g=Math.max(30,l-35),h=e.url.length>g?e.url.substring(0,g-2)+"..":e.url;we.push([r,s,a,c,h]),we.length>100&&(we=we.slice(-100),n&&n.length>100&&n.splice(0,n.length-100));let S=[["Time","Callback","Duration","Status","Path"],...we];o.setData(S)}function Ao(o,e,n,i,r){try{let s=require("blessed");t.debug(`Showing request details for ${o.httpMethod} ${o.url}`);let a=s.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 "}),c=s.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"}});s.box({parent:a,top:2,left:2,width:"100%-4",height:1,content:`{bold}{cyan-fg}${o.httpMethod}{/} {blue-fg}${o.url}{/} - {${Oo(o.statusCode)}}${o.statusCode}{/} - {yellow-fg}${o.executionTimeMs}ms{/} - {magenta-fg}${o.memoryUsedMB||0}MB{/}`,tags:!0,style:{bg:"black"}});let l=s.box({parent:a,top:4,left:2,width:"100%-4",height:"100%-5",scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,content:Ro(o)});l.focus(),e.render();let u=!0,g=()=>{u&&(u=!1,a.destroy(),n.focus(),e.render())};e.key(["escape","q"],()=>{u&&g()}),e.key(["up","k"],()=>{u&&(l.scroll(-1),e.render())}),e.key(["down","j"],()=>{u&&(l.scroll(1),e.render())}),e.on("keypress",(h,S)=>{u&&t.debug(`Key pressed: ch="${h}" key=${JSON.stringify(S)}`)}),e.key(["J","j"],()=>{u&&(t.debug("J/j key pressed - attempting JSON copy"),c.setContent("{black-bg}{yellow-fg} J KEY PRESSED - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let h=JSON.stringify(o,null,2);t.debug(`JSON content length: ${h.length}`),t.debug("Attempting native clipboard copy"),We(h).then(()=>{c.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded"),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(S=>{t.debug(`Native clipboard failed: ${S.message}`);let w=_e.default.join(Oe.default.tmpdir(),`sinch-request-${Date.now()}.json`);Fe.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 JSON saved to: ${w}{/}`),t.debug(`Saved to temp file: ${w}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(h){t.debug(`JSON copy error: ${h.message}`),c.setContent(`{red-fg}\u2717 Copy failed: ${h.message}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["C","c"],()=>{u&&(t.debug("C/c key pressed - attempting cURL copy"),c.setContent("{black-bg}{yellow-fg} C KEY PRESSED - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let h=un(o);t.debug("Attempting native clipboard copy for cURL"),We(h).then(()=>{c.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded for cURL"),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(S=>{t.debug(`Native clipboard failed for cURL: ${S.message}`);let w=_e.default.join(Oe.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);Fe.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 cURL saved to: ${w}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(h){t.debug(`cURL copy error: ${h.message}`),c.setContent(`{red-fg}\u2717 Copy failed: ${h.message}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["1"],()=>{u&&(t.debug("1 key pressed - copying JSON (alternative binding)"),c.setContent("{black-bg}{yellow-fg} 1 KEY - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let h=JSON.stringify(o,null,2);We(h).then(()=>{c.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(S=>{let w=_e.default.join(Oe.default.tmpdir(),`sinch-request-${Date.now()}.json`);Fe.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 JSON saved to: ${w}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(h){c.setContent(`{red-fg}\u2717 Copy failed: ${h.message}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["2"],()=>{u&&(t.debug("2 key pressed - copying cURL (alternative binding)"),c.setContent("{black-bg}{yellow-fg} 2 KEY - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let h=un(o);We(h).then(()=>{c.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(S=>{let w=_e.default.join(Oe.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);Fe.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 cURL saved to: ${w}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(h){c.setContent(`{red-fg}\u2717 Copy failed: ${h.message}{/}`),e.render(),setTimeout(()=>{u&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))})}catch(s){t.debug(`Error in showBlessedZoomedRequest: ${s.message}`)}}function Ro(o){let e="";return e+=`
46
+ `,e+=To(o),e+=`
47
+ `,e+=jo(o),e+=`
48
+ `,e+=Do(o),e}function To(o){let e="",n=process.stdout.columns-6;e+="{bold}{green-fg}\u250C\u2500 REQUEST "+"\u2500".repeat(Math.max(0,n-10))+`\u2510{/}
49
+ `;let i=_o(o);if(i&&(e+=`{green-fg}\u2502{/} {bold}Call ID:{/} {cyan-fg}${i}{/}
50
50
  `),o.headers){e+=`{green-fg}\u2502{/} {bold}Headers:{/}
51
51
  `;try{let r=typeof o.headers=="string"?JSON.parse(o.headers):o.headers;Object.entries(r).forEach(([s,a])=>{let c=` ${s}: ${a}`;e+=ee(c,n-2,"{green-fg}\u2502{/} ")})}catch{e+=ee(` ${o.headers}`,n-2,"{green-fg}\u2502{/} ")}}if(o.requestBody){e+=`{green-fg}\u2502{/} {bold}Body:{/}
52
52
  `;try{let r=JSON.parse(o.requestBody);JSON.stringify(r,null,2).split(`
53
53
  `).forEach(a=>{e+=ee(a,n-2,"{green-fg}\u2502{/} ")})}catch{e+=ee(o.requestBody,n-2,"{green-fg}\u2502{/} ")}}return e+="{green-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
54
- `,e}function Oo(o){let e="",n=process.stdout.columns-6;if(e+="{bold}{blue-fg}\u250C\u2500 RESPONSE "+"\u2500".repeat(Math.max(0,n-11))+`\u2510{/}
54
+ `,e}function jo(o){let e="",n=process.stdout.columns-6;if(e+="{bold}{blue-fg}\u250C\u2500 RESPONSE "+"\u2500".repeat(Math.max(0,n-11))+`\u2510{/}
55
55
  `,o.responseHeaders){e+=`{blue-fg}\u2502{/} {bold}Headers:{/}
56
56
  `;try{let i=typeof o.responseHeaders=="string"?JSON.parse(o.responseHeaders):o.responseHeaders;Object.entries(i).forEach(([r,s])=>{let a=` ${r}: ${s}`;e+=ee(a,n-2,"{blue-fg}\u2502{/} ")})}catch{e+=ee(` ${o.responseHeaders}`,n-2,"{blue-fg}\u2502{/} ")}}if(o.responseBody){e+=`{blue-fg}\u2502{/} {bold}Body:{/}
57
57
  `;try{let i=JSON.parse(o.responseBody);JSON.stringify(i,null,2).split(`
58
58
  `).forEach(s=>{e+=ee(s,n-2,"{blue-fg}\u2502{/} ")})}catch{e+=ee(o.responseBody,n-2,"{blue-fg}\u2502{/} ")}}return o.errorMessage&&(e+=`{blue-fg}\u2502{/} {bold}{red-fg}Error:{/}
59
59
  `,e+=ee(o.errorMessage,n-2,"{blue-fg}\u2502{/} ")),e+="{blue-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
60
- `,e}function Lo(o){let e="",n=process.stdout.columns-6;return e+="{bold}{magenta-fg}\u250C\u2500 CONSOLE LOGS "+"\u2500".repeat(Math.max(0,n-15))+`\u2510{/}
61
- `,o.logs&&o.logs.length>0?o.logs.forEach((i,r)=>{let s=new Date(i.timestamp).toLocaleTimeString(),a=i.level.toUpperCase().padEnd(5),c=xo(i.level),l=`${s} [${a}] ${i.message}`;e+=ee(l,n-2,"{magenta-fg}\u2502{/} ",c)}):e+=`{magenta-fg}\u2502{/} {gray-fg}No console logs for this request{/}
60
+ `,e}function Do(o){let e="",n=process.stdout.columns-6;return e+="{bold}{magenta-fg}\u250C\u2500 CONSOLE LOGS "+"\u2500".repeat(Math.max(0,n-15))+`\u2510{/}
61
+ `,o.logs&&o.logs.length>0?o.logs.forEach((i,r)=>{let s=new Date(i.timestamp).toLocaleTimeString(),a=i.level.toUpperCase().padEnd(5),c=Fo(i.level),l=`${s} [${a}] ${i.message}`;e+=ee(l,n-2,"{magenta-fg}\u2502{/} ",c)}):e+=`{magenta-fg}\u2502{/} {gray-fg}No console logs for this request{/}
62
62
  `,e+="{magenta-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
63
63
  `,e}function ee(o,e,n,i=""){if(!o)return"";let r="";return o.split(`
64
64
  `).forEach(a=>{if(a.length<=e)r+=`${n}${i}${a}{/}
65
65
  `;else{let c=a,l=!0;for(;c.length>e;){let u=e-(l?0:4),g=c.substring(0,u);r+=`${n}${l?"":" "}${i}${g}{/}
66
66
  `,c=c.substring(u),l=!1}c.length>0&&(r+=`${n}${l?"":" "}${i}${c}{/}
67
- `)}}),r}function xo(o){switch(o.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 _o(o){return o>=200&&o<300?"green-fg":o>=300&&o<400?"yellow-fg":o>=400&&o<500?"red-fg":o>=500?"red-fg}{bold":"white-fg"}function No(o){try{if(o.requestBody){let e=JSON.parse(o.requestBody);return e.callId||e.callid||e.call_id||null}}catch{}return null}function Uo(o){try{let e="";if(o.requestBody){let n=JSON.parse(o.requestBody);if(n.event)e=n.event.toLowerCase();else{let i=o.url.split("/").filter(r=>r);e=i[i.length-1]||""}return e||""}}catch{}return""}async function Ko(o,e,n){try{d.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=Bo(n.since);a&&(i.startTime=a.toISOString())}let r=await o.getFunctionLogs(e,i);if(d.stop(),t.debug("Historical API response:",{totalRequests:r.requests?.length||0,firstRequest:r.requests?.[0]||"No requests",responseKeys:Object.keys(r)}),!r.requests||r.requests.length===0){t.info("\u{1F4DD} No logs found"),t.info("\u{1F4A1} Logs will appear here after function receives requests");return}let s=r.requests;t.debug("Historical requests:",{totalRequests:s.length,firstRequest:s[0]||"No requests",requestTimestamps:s.slice(0,3).map(a=>a.startTime)}),await Vo(s,"HISTORICAL","Function")}catch(i){throw d.stop(),i}}function Bo(o){if(!o)return null;let e=o.match(/^(\d+)([smhd])$/);if(!e)return null;let n=parseInt(e[1]),i=e[2],r=new Date;switch(i){case"s":return new Date(r.getTime()-n*1e3);case"m":return new Date(r.getTime()-n*60*1e3);case"h":return new Date(r.getTime()-n*60*60*1e3);case"d":return new Date(r.getTime()-n*24*60*60*1e3);default:return null}}async function Vo(o,e,n){let i=hn(o,e,n);o.forEach(r=>{mn(i.table,r,o)}),i.screen.render(),await new Promise(()=>{})}function hn(o,e,n){let i=require("blessed");process.stdout.write("\x1Bc"),Se=[];let r=i.screen({smartCSR:!0,title:`Sinch Functions - ${n} Logs`,fullUnicode:!0}),s=i.box({parent:r,top:0,left:0,width:"100%",height:1,content:yn(e,n),tags:!0,style:{bg:"black"}}),a=i.listtable({parent:r,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}),c=["Time","Callback","Duration","Status","Path"];a.setData([c]),a.focus(),r.key(["q","C-c"],()=>{process.exit(0)});let l=()=>{try{let u=a.selected||0,g=u-1;if(g>=0&&g<o.length&&o[g])t.debug(`Opening request details for index ${g}`),Do(o[g],r,a,s,n);else{let h=`Selected: ${u}, DataIndex: ${g}, Requests: ${o.length}, TableData: ${Se.length}`;t.debug(`Selection out of bounds: ${h}`)}}catch(u){t.debug(`Error in request selection: ${u.message}`)}};return r.key(["enter"],l),a.on("select",(u,g)=>{l()}),r.on("wheelup",()=>{a.focused&&(a.scroll(-1),r.render())}),r.on("wheeldown",()=>{a.focused&&(a.scroll(1),r.render())}),{screen:r,table:a,statusBar:s}}function yn(o,e){switch(o){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 dn(o,e,n){o.setContent(yn(e,n))}function Ge(o){return new Promise((e,n)=>{let i,r;process.platform==="win32"?(i="clip",r=[]):process.platform==="darwin"?(i="pbcopy",r=[]):(i="xclip",r=["-selection","clipboard"]),t.debug(`Using clipboard command: ${i} with args:`,r);let s=(0,pt.spawn)(i,r,{stdio:["pipe","ignore","pipe"]}),a="";s.stderr.on("data",c=>{a+=c.toString()}),s.on("error",c=>{if(t.debug(`Clipboard process error: ${c.message}`),process.platform==="linux"&&i==="xclip"){t.debug("Trying xsel as fallback");let l=(0,pt.spawn)("xsel",["--clipboard","--input"],{stdio:["pipe","ignore","pipe"]});l.on("error",u=>{n(new Error(`No clipboard utility found: ${c.message} / ${u.message}`))}),l.on("close",u=>{u===0?e():n(new Error(`xsel failed with code ${u}`))}),l.stdin&&(l.stdin.write(o),l.stdin.end());return}n(c)}),s.on("close",c=>{c===0?(t.debug("Clipboard copy successful"),e()):(t.debug(`Clipboard process failed with code ${c}, error: ${a}`),n(new Error(`Clipboard command failed with code ${c}: ${a}`)))}),s.stdin&&(s.stdin.write(o),s.stdin.end())})}function pn(o){let e=process.platform==="win32",n=`curl -X ${o.httpMethod}`,i={};if(o.headers)try{i=typeof o.headers=="string"?JSON.parse(o.headers):o.headers}catch{}let r=o.url;if(r&&!r.startsWith("http")){let s=i.host||i.Host;s&&(r=`${s.includes("localhost")||s.includes("127.0.0.1")?"http":"https"}://${s}${r.startsWith("/")?r:"/"+r}`)}if(n+=` "${r}"`,Object.entries(i).forEach(([s,a])=>{let c=["content-length","connection","user-agent"];o.url.startsWith("http")||c.push("host"),c.includes(s.toLowerCase())||(e?n+=` -H "${s}: ${a}"`:n+=` \\
67
+ `)}}),r}function Fo(o){switch(o.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 Oo(o){return o>=200&&o<300?"green-fg":o>=300&&o<400?"yellow-fg":o>=400&&o<500?"red-fg":o>=500?"red-fg}{bold":"white-fg"}function _o(o){try{if(o.requestBody){let e=JSON.parse(o.requestBody);return e.callId||e.callid||e.call_id||null}}catch{}return null}function xo(o){try{let e="";if(o.requestBody){let n=JSON.parse(o.requestBody);if(n.event)e=n.event.toLowerCase();else{let i=o.url.split("/").filter(r=>r);e=i[i.length-1]||""}return e||""}}catch{}return""}async function Lo(o,e,n){try{d.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=No(n.since);a&&(i.startTime=a.toISOString())}let r=await o.getFunctionLogs(e,i);if(d.stop(),t.debug("Historical API response:",{totalRequests:r.requests?.length||0,firstRequest:r.requests?.[0]||"No requests",responseKeys:Object.keys(r)}),!r.requests||r.requests.length===0){t.info("\u{1F4DD} No logs found"),t.info("\u{1F4A1} Logs will appear here after function receives requests");return}let s=r.requests;t.debug("Historical requests:",{totalRequests:s.length,firstRequest:s[0]||"No requests",requestTimestamps:s.slice(0,3).map(a=>a.startTime)}),await Uo(s,"HISTORICAL","Function")}catch(i){throw d.stop(),i}}function No(o){if(!o)return null;let e=o.match(/^(\d+)([smhd])$/);if(!e)return null;let n=parseInt(e[1]),i=e[2],r=new Date;switch(i){case"s":return new Date(r.getTime()-n*1e3);case"m":return new Date(r.getTime()-n*60*1e3);case"h":return new Date(r.getTime()-n*60*60*1e3);case"d":return new Date(r.getTime()-n*24*60*60*1e3);default:return null}}async function Uo(o,e,n){let i=gn(o,e,n);o.forEach(r=>{fn(i.table,r,o)}),i.screen.render(),await new Promise(()=>{})}function gn(o,e,n){let i=require("blessed");process.stdout.write("\x1Bc"),we=[];let r=i.screen({smartCSR:!0,title:`Sinch Functions - ${n} Logs`,fullUnicode:!0}),s=i.box({parent:r,top:0,left:0,width:"100%",height:1,content:mn(e,n),tags:!0,style:{bg:"black"}}),a=i.listtable({parent:r,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}),c=["Time","Callback","Duration","Status","Path"];a.setData([c]),a.focus(),r.key(["q","C-c"],()=>{process.exit(0)});let l=()=>{try{let u=a.selected||0,g=u-1;if(g>=0&&g<o.length&&o[g])t.debug(`Opening request details for index ${g}`),Ao(o[g],r,a,s,n);else{let h=`Selected: ${u}, DataIndex: ${g}, Requests: ${o.length}, TableData: ${we.length}`;t.debug(`Selection out of bounds: ${h}`)}}catch(u){t.debug(`Error in request selection: ${u.message}`)}};return r.key(["enter"],l),a.on("select",(u,g)=>{l()}),r.on("wheelup",()=>{a.focused&&(a.scroll(-1),r.render())}),r.on("wheeldown",()=>{a.focused&&(a.scroll(1),r.render())}),{screen:r,table:a,statusBar:s}}function mn(o,e){switch(o){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 ln(o,e,n){o.setContent(mn(e,n))}function We(o){return new Promise((e,n)=>{let i,r;process.platform==="win32"?(i="clip",r=[]):process.platform==="darwin"?(i="pbcopy",r=[]):(i="xclip",r=["-selection","clipboard"]),t.debug(`Using clipboard command: ${i} with args:`,r);let s=(0,ut.spawn)(i,r,{stdio:["pipe","ignore","pipe"]}),a="";s.stderr.on("data",c=>{a+=c.toString()}),s.on("error",c=>{if(t.debug(`Clipboard process error: ${c.message}`),process.platform==="linux"&&i==="xclip"){t.debug("Trying xsel as fallback");let l=(0,ut.spawn)("xsel",["--clipboard","--input"],{stdio:["pipe","ignore","pipe"]});l.on("error",u=>{n(new Error(`No clipboard utility found: ${c.message} / ${u.message}`))}),l.on("close",u=>{u===0?e():n(new Error(`xsel failed with code ${u}`))}),l.stdin&&(l.stdin.write(o),l.stdin.end());return}n(c)}),s.on("close",c=>{c===0?(t.debug("Clipboard copy successful"),e()):(t.debug(`Clipboard process failed with code ${c}, error: ${a}`),n(new Error(`Clipboard command failed with code ${c}: ${a}`)))}),s.stdin&&(s.stdin.write(o),s.stdin.end())})}function un(o){let e=process.platform==="win32",n=`curl -X ${o.httpMethod}`,i={};if(o.headers)try{i=typeof o.headers=="string"?JSON.parse(o.headers):o.headers}catch{}let r=o.url;if(r&&!r.startsWith("http")){let s=i.host||i.Host;s&&(r=`${s.includes("localhost")||s.includes("127.0.0.1")?"http":"https"}://${s}${r.startsWith("/")?r:"/"+r}`)}if(n+=` "${r}"`,Object.entries(i).forEach(([s,a])=>{let c=["content-length","connection","user-agent"];o.url.startsWith("http")||c.push("host"),c.includes(s.toLowerCase())||(e?n+=` -H "${s}: ${a}"`:n+=` \\
68
68
  -H "${s}: ${a}"`)}),o.requestBody&&["POST","PUT","PATCH"].includes(o.httpMethod)){try{let s=JSON.parse(o.requestBody),a=JSON.stringify(s);e?n+=` -d '${a.replace(/'/g,"\\'")}'`:n+=` \\
69
69
  -d '${JSON.stringify(s,null,2)}'`}catch{e?n+=` -d '${o.requestBody.replace(/'/g,"\\'")}'`:n+=` \\
70
70
  -d '${o.requestBody}'`}n.toLowerCase().includes("content-type")||(e?n+=' -H "Content-Type: application/json"':n+=` \\
71
71
  -H "Content-Type: application/json"`)}return e?n+=" -v":n+=` \\
72
- -v`,n}wn.exports=ft});var kn=N((dr,$n)=>{"use strict";var M=m(require("chalk")),Cn=m(require("inquirer")),Sn=require("commander");L();I();K();j();var vn=new Sn.Command("delete");vn.alias("del").description("Delete a function").argument("<function-id>","Function ID to delete").option("-f, --force","Skip confirmation").action(async(o,e)=>{try{await p.load();let n=new A(p.getApiConfig());d.start("Loading function details...");let i=await n.getFunction(o);if(d.stop(),t.newline(),t.info("\u{1F5D1}\uFE0F Function to delete:"),t.info(` Name: ${M.default.cyan(i.name)}`),t.info(` ID: ${M.default.gray(i.id)}`),t.info(` Runtime: ${M.default.yellow(i.runtime)}`),t.info(` Status: ${qo(i.status)}`),t.info(` Created: ${new Date(i.createdAt).toLocaleString()}`),i.containerAppUrl&&t.info(` URL: ${M.default.blue(i.containerAppUrl)}`),!e.force){t.newline(),t.warn("\u26A0\uFE0F This action cannot be undone!");let{confirm:r}=await Cn.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete function '${i.name}'?`,default:!1}]);if(!r){t.info("Deletion cancelled");return}}d.start("Deleting function..."),await n.deleteFunction(o),d.succeed(`Function '${i.name}' deleted successfully`),p.isInProject()&&p.getProjectConfig()?.functionId===o&&(p.set("functionId",void 0,!0),await p.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: ${M.default.cyan("sinch functions list")}`),t.info(` \u2022 Deploy new function: ${M.default.cyan("sinch functions deploy")}`)}catch(n){d.stop(),n.message.includes("404")||n.message.includes("not found")?(t.error(`Function '${o}' not found`),t.info("\u{1F4A1} List available functions with:"),t.info(` ${M.default.cyan("sinch functions list")}`)):t.error(`Failed to delete function: ${n.message}`),process.exit(1)}});function qo(o){return{Running:M.default.green("\u2705 Running"),Failed:M.default.red("\u274C Failed"),Pending:M.default.yellow("\u23F3 Pending"),Building:M.default.blue("\u{1F528} Building")}[o]||M.default.gray(o)}$n.exports=vn});var En=N((yr,An)=>{"use strict";var Pn=require("commander"),gt=m(require("fs-extra")),mt=m(require("path")),ve=m(require("chalk"));I();K();j();lt();L();var ht=new Pn.Command("docs");ht.description("Generate documentation for voice functions (saves to README.md)");ht.option("-f, --fresh","Force regeneration (skip cache)").option("-u, --update","Update documentation for deployed function via API").action(async o=>{try{await p.load(),o.update?await Jo():await Mo(o)}catch(e){d.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 Mo(o){d.start("\u{1F916} Generating documentation...");let e=await at();d.succeed("\u2705 Documentation generated!"),await ct(e,"README.md"),await Wo()}async function Jo(){let o=mt.default.basename(process.cwd());d.start("\u{1F4D6} Reading local README.md...");let e=mt.default.join(process.cwd(),"README.md");if(!await gt.default.pathExists(e))throw new Error("README.md not found. Run `sinch functions docs` first to generate documentation locally.");if(!(await gt.default.readFile(e,"utf8")).trim())throw new Error("README.md is empty. Run `sinch functions docs` first to generate documentation.");d.text="\u{1F50D} Finding deployed function...";let s=(await new A(p.getApiConfig()).listFunctions()).find(a=>a.name===o);if(!s)throw new Error(`Function '${o}' not found in project. Make sure it's deployed first.`);d.text="\u{1F4E4} Uploading documentation content...",t.info("Documentation content ready for update"),d.succeed("\u2705 Documentation updated!"),t.newline(),t.success(`\u{1F4C4} Documentation updated for deployed function: ${ve.default.cyan(o)}`),t.info(""),t.info("\u2728 Your function documentation has been updated:"),t.info(` \u2022 Function ID: ${ve.default.gray(s.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 "+o)}`),t.newline(),t.info("\u{1F4A1} The updated documentation is now available in the dashboard!")}async function Wo(){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")}An.exports=ht});var jn=N((vr,Dn)=>{"use strict";var F=m(require("chalk")),yt=m(require("inquirer")),In=require("commander"),G=m(require("fs-extra")),ae=m(require("path")),Rn=m(require("adm-zip"));L();I();K();j();var Tn=new In.Command("download");Tn.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("--version <version>","Download specific version (if available)").option("-f, --force","Overwrite existing directory without prompting").action(async(o,e)=>{try{await p.load();let n=new A(p.getApiConfig()),i=o;if(!i&&!e.nonInteractive){let u=await Ho(n);if(!u){t.info("Download cancelled");return}i=u}i||(t.error("Function ID required. Provide as argument or select interactively"),t.info(`Usage: ${F.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABCDE")}`),t.info(` or: ${F.default.cyan("sinch functions download")} (interactive selection)`),process.exit(1)),d.start("\u{1F4E1} Fetching function metadata...");let r=await n.getFunction(i);d.succeed("Function metadata loaded");let s=ae.join("functions",r.name),a=e.output||s,c=ae.resolve(a);if(await G.pathExists(c)){if(!e.force){let{overwrite:u}=await yt.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${a}' already exists. Overwrite?`,default:!1}]);if(!u){t.info("Download cancelled");return}}d.start("\u{1F5D1}\uFE0F Removing existing directory..."),await G.remove(c),d.succeed("Existing directory removed")}d.start("\u{1F4E5} Downloading function source code...");let l=await n.downloadFunction(i);if(d.succeed("Source code downloaded"),e.extract!==!1){d.start("\u{1F4E6} Extracting files..."),await G.ensureDir(c);let u=new Rn.default(l),g=u.getEntries();u.extractAllTo(c,!0),d.succeed(`\u{1F4E6} Extracted ${g.length} files`);let h=ae.join(c,"sinch-metadata.json"),S={functionId:r.id,name:r.name,runtime:r.runtime,status:r.status,downloadedAt:new Date().toISOString(),url:r.containerAppUrl,configuration:r.configuration};await G.writeJson(h,S,{spaces:2}),t.newline(),t.success("\u2705 Function downloaded successfully!"),t.newline(),t.info(`\u{1F4C1} Location: ${F.default.cyan(a)}`),t.info(`\u{1F4CB} Files: ${g.length} files extracted`);let w=ae.join(c,"sinch.json");await G.pathExists(w)&&t.info("\u{1F527} Config: sinch.json found"),t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 Navigate: ${F.default.cyan(`cd ${a}`)}`),t.info(` \u2022 Run locally: ${F.default.cyan("sinch functions dev")}`),t.info(` \u2022 Deploy changes: ${F.default.cyan("sinch functions deploy")}`)}else{let u=`${r.name}.zip`,g=e.output?ae.resolve(e.output):ae.resolve(u);d.start(`\u{1F4BE} Saving as ${u}...`),await G.writeFile(g,l),d.succeed("ZIP file saved"),t.newline(),t.success("\u2705 Function downloaded as ZIP!"),t.info(`\u{1F4C1} File: ${F.default.cyan(g)}`),t.info(`\u{1F4E6} Size: ${(l.length/1024).toFixed(2)} KB`)}}catch(n){d.stop(),n.message.includes("404")||n.message.includes("not found")?(t.error(`Function not found with ID: ${o}`),t.info("\u{1F4A1} List available functions with:"),t.info(` ${F.default.cyan("sinch functions list")}`),t.info("\u{1F4A1} Or use interactive selection:"),t.info(` ${F.default.cyan("sinch functions download")}`)):t.error(`Failed to download function: ${n.message}`),process.exit(1)}});async function Ho(o){try{d.start("\u{1F4CB} Loading functions...");let e=await o.listFunctions();if(d.stop(),!e.functions||e.functions.length===0)return t.warn("No functions found to download"),null;let n=e.functions.map(r=>({name:`${F.default.cyan(r.name.padEnd(20))} ${F.default.yellow(r.runtime.padEnd(8))} ${Go(r.status)}`,value:r.id,short:r.name}));t.newline();let{selectedFunction:i}=await yt.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function to download:",choices:n,pageSize:15}]);return i}catch(e){throw d.stop(),e}}function Go(o){return{Running:F.default.green("\u2705 Running"),Failed:F.default.red("\u274C Failed"),Pending:F.default.yellow("\u23F3 Pending"),Building:F.default.blue("\u{1F528} Building")}[o]||F.default.gray(o)}Dn.exports=Tn});var Ln=N(($r,On)=>{"use strict";var Fn=require("commander"),Yo=Ot(),zo=Ut(),Qo=Xt(),Zo=rn(),Xo=un(),ei=bn(),ti=kn(),ni=En(),oi=jn(),Y=new Fn.Command("functions");Y.description("Manage Sinch Functions");Y.addCommand(Yo);Y.addCommand(zo);Y.addCommand(Qo);Y.addCommand(oi);Y.addCommand(Zo);Y.addCommand(Xo);Y.addCommand(ei);Y.addCommand(ti);Y.addCommand(ni);On.exports=Y});var Nn=N((Ir,_n)=>{"use strict";var xn=require("commander"),J=m(require("chalk"));L();I();K();j();var te=new xn.Command("templates");te.description("Browse and manage function templates");te.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(o,e)=>{try{await p.load();let n=new A(p.getApiConfig());d.start("Loading templates...");let i;if(o?i=await n.listRuntimeTemplates(o,e.category):i=await n.listAllTemplates(e.category),d.stop(),i.templates.length===0){t.info(`No templates found${o?` for ${o}`:""}${e.category?` in category ${e.category}`:""}`);return}let r=`Available Templates${o?` (${o})`:""}${e.category?` - ${e.category}`:""}`;if(t.title(r),e.detailed)i.templates.forEach((s,a)=>{a>0&&t.newline(),t.log(J.default.bold.blue(`${s.name}`)),t.log(` Runtime: ${s.runtime}`),t.log(` Category: ${s.category}`),t.log(` Description: ${s.description}`),s.tags&&s.tags.length>0&&t.log(` Tags: ${s.tags.map(c=>J.default.gray(c)).join(", ")}`),t.log(` Path: ${J.default.gray(s.path)}`)});else{let s=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"],s)}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){d.stop(),t.error(`Failed to list templates: ${n.message}`),process.exit(1)}});te.command("show").description("Show detailed template information").argument("<template>",'Template name in format "runtime/template-name"').action(async o=>{try{await p.load();let e=new A(p.getApiConfig());if(!o.includes("/"))throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');let n=o.split("/"),i=n[0],r=n[1];if(!i||!r)throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');d.start(`Loading template details for ${o}...`);let s=await e.getTemplateDetails(i,r);d.stop(),t.title(`Template: ${s.name}`),t.newline(),t.log(J.default.bold("Basic Information:")),t.log(` Runtime: ${s.runtime}`),t.log(` Category: ${s.category}`),t.log(` Description: ${s.description}`),s.tags&&s.tags.length>0&&t.log(` Tags: ${s.tags.map(a=>J.default.blue(a)).join(", ")}`),s.variables&&Object.keys(s.variables).length>0&&(t.newline(),t.log(J.default.bold("Template Variables:")),Object.entries(s.variables).forEach(([a,c])=>{t.log(` ${a}: ${J.default.gray(c)}`)})),s.files&&s.files.length>0&&(t.newline(),t.log(J.default.bold("Files:")),s.files.forEach(a=>{t.log(` ${J.default.gray("\u2022")} ${a}`)})),s.readmeContent&&(t.newline(),t.log(J.default.bold("README:")),s.readmeContent.split(`
73
- `).slice(0,10).forEach(c=>{t.log(` ${J.default.gray(c)}`)}),s.readmeContent.split(`
74
- `).length>10&&t.log(` ${J.default.gray("... (truncated)")}`)),t.newline(),t.info(`Use "sinch functions init --template ${o}" to create a function from this template`)}catch(e){d.stop(),t.error(`Failed to show template details: ${e.message}`),process.exit(1)}});te.command("node").description("List Node.js templates").option("-c, --category <category>","Filter by category").action(async o=>{let e=te.commands.find(n=>n.name()==="list");e&&await e.action("node",o)});te.command("csharp").description("List C# templates").option("-c, --category <category>","Filter by category").action(async o=>{let e=te.commands.find(n=>n.name()==="list");e&&await e.action("csharp",o)});te.command("python").description("List Python templates").option("-c, --category <category>","Filter by category").action(async o=>{let e=te.commands.find(n=>n.name()==="list");e&&await e.action("python",o)});_n.exports=te});var Vn=N((jr,Bn)=>{"use strict";var Un=require("commander"),ce=m(require("chalk")),Kn=m(require("inquirer"));I();K();j();var le=new Un.Command("voice");le.description("Manage Sinch Voice applications and settings");le.command("apps").alias("applications").description("List your Voice applications").action(async()=>{try{await p.load(),await Re()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let o=await Ye(),e=p.getPublicCredentialInfo()?.applicationKey;if(!e){t.error('No default application key found. Run "sinch auth login" first.');return}d.start("Loading application info...");try{await o.voice.applications.getCallbackURLs({applicationkey:e});let n=await o.voice.applications.get(e);d.stop(),t.title("Voice Application (Default)"),t.info(`App Key: ${e}`),t.info(`Display Name: ${n.displayName||"Not set"}`),t.info(`Callback URL: ${n.capability?.voice?.webhooks?.url||"Not set"}`)}catch(n){d.stop(),t.error(`Could not get application info: ${n.message}`),t.info(`Default Application Key: ${e}`),t.info("(Use this key with other voice commands)")}}catch(o){d.stop(),t.error(`Failed to list applications: ${o.message}`),process.exit(1)}});le.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(o,e)=>{try{await p.load(),await Re()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await Ye(),i=e.appKey;if(!i){let r=p.getPublicCredentialInfo()?.applicationKey;r||(t.error('No default application key found. Run "sinch auth login" first.'),process.exit(1)),i=r,t.info(`Using default application: ${i}`)}if(!o){let{newUrl:r}=await Kn.default.prompt([{type:"input",name:"newUrl",message:"Enter new callback URL:",validate:s=>{if(!s)return"URL is required";try{return new URL(s),!0}catch{return"Please enter a valid URL"}}}]);o=r}d.start("Updating callback URL...");try{let r=await n.voice.applications.get(i),s={...r,capability:{...r.capability,voice:{...r.capability?.voice,webhooks:{...r.capability?.voice?.webhooks,url:o,method:"POST"}}}};await n.voice.applications.update(i,s),d.succeed("Callback URL updated successfully!"),t.newline(),t.info(`Application: ${r.displayName||i}`),t.info(`New callback URL: ${o}`),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(r){throw d.fail("Failed to update callback URL"),r}}catch(n){d.stop(),t.error(`Failed to update callback URL: ${n.message}`),process.exit(1)}});le.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 o=>{try{await p.load(),await Re()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=await p.getApplicationCredentials();e||(t.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let n=o.appKey||e.applicationKey;if(t.info("\u{1F50D} Getting callback URLs..."),t.newline(),o.curl){let i=`${e.applicationKey}:${e.applicationSecret}`,r=Buffer.from(i).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(ce.default.gray("```bash"));let s=`curl -X GET \\
72
+ -v`,n}hn.exports=dt});var vn=N((lr,Sn)=>{"use strict";var J=m(require("chalk")),wn=m(require("inquirer")),Cn=require("commander");_();A();B();F();var bn=new Cn.Command("delete");bn.alias("del").description("Delete a function").argument("<function-id>","Function ID to delete").option("-f, --force","Skip confirmation").action(async(o,e)=>{try{await p.load();let n=new E(p.getApiConfig());d.start("Loading function details...");let i=await n.getFunction(o);if(d.stop(),t.newline(),t.info("\u{1F5D1}\uFE0F Function to delete:"),t.info(` Name: ${J.default.cyan(i.name)}`),t.info(` ID: ${J.default.gray(i.id)}`),t.info(` Runtime: ${J.default.yellow(i.runtime)}`),t.info(` Status: ${Bo(i.status)}`),t.info(` Created: ${new Date(i.createdAt).toLocaleString()}`),i.containerAppUrl&&t.info(` URL: ${J.default.blue(i.containerAppUrl)}`),!e.force){t.newline(),t.warn("\u26A0\uFE0F This action cannot be undone!");let{confirm:r}=await wn.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete function '${i.name}'?`,default:!1}]);if(!r){t.info("Deletion cancelled");return}}d.start("Deleting function..."),await n.deleteFunction(o),d.succeed(`Function '${i.name}' deleted successfully`),p.isInProject()&&p.getProjectConfig()?.functionId===o&&(p.set("functionId",void 0,!0),await p.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: ${J.default.cyan("sinch functions list")}`),t.info(` \u2022 Deploy new function: ${J.default.cyan("sinch functions deploy")}`)}catch(n){d.stop(),n.message.includes("404")||n.message.includes("not found")?(t.error(`Function '${o}' not found`),t.info("\u{1F4A1} List available functions with:"),t.info(` ${J.default.cyan("sinch functions list")}`)):t.error(`Failed to delete function: ${n.message}`),process.exit(1)}});function Bo(o){return{Running:J.default.green("\u2705 Running"),Failed:J.default.red("\u274C Failed"),Pending:J.default.yellow("\u23F3 Pending"),Building:J.default.blue("\u{1F528} Building")}[o]||J.default.gray(o)}Sn.exports=bn});var Pn=N((mr,kn)=>{"use strict";var $n=require("commander"),pt=m(require("fs-extra")),ft=m(require("path")),Ce=m(require("chalk"));A();B();F();at();_();var gt=new $n.Command("docs");gt.description("Generate documentation for voice functions (saves to README.md)");gt.option("-f, --fresh","Force regeneration (skip cache)").option("-u, --update","Update documentation for deployed function via API").action(async o=>{try{await p.load(),o.update?await qo():await Ko(o)}catch(e){d.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 Ko(o){d.start("\u{1F916} Generating documentation...");let e=await rt();d.succeed("\u2705 Documentation generated!"),await st(e,"README.md"),await Vo()}async function qo(){let o=ft.default.basename(process.cwd());d.start("\u{1F4D6} Reading local README.md...");let e=ft.default.join(process.cwd(),"README.md");if(!await pt.default.pathExists(e))throw new Error("README.md not found. Run `sinch functions docs` first to generate documentation locally.");if(!(await pt.default.readFile(e,"utf8")).trim())throw new Error("README.md is empty. Run `sinch functions docs` first to generate documentation.");d.text="\u{1F50D} Finding deployed function...";let s=(await new E(p.getApiConfig()).listFunctions()).find(a=>a.name===o);if(!s)throw new Error(`Function '${o}' not found in project. Make sure it's deployed first.`);d.text="\u{1F4E4} Uploading documentation content...",t.info("Documentation content ready for update"),d.succeed("\u2705 Documentation updated!"),t.newline(),t.success(`\u{1F4C4} Documentation updated for deployed function: ${Ce.default.cyan(o)}`),t.info(""),t.info("\u2728 Your function documentation has been updated:"),t.info(` \u2022 Function ID: ${Ce.default.gray(s.id)}`),t.info(` \u2022 Source: ${Ce.default.gray("Local README.md")}`),t.info(` \u2022 Updated: ${Ce.default.gray(new Date().toLocaleString())}`),t.info(` \u2022 View in dashboard: ${Ce.default.cyan("Dashboard \u2192 Functions \u2192 "+o)}`),t.newline(),t.info("\u{1F4A1} The updated documentation is now available in the dashboard!")}async function Vo(){t.newline(),t.success(`\u{1F4C4} Documentation updated in: ${Ce.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")}kn.exports=gt});var Tn=N((br,Rn)=>{"use strict";var O=m(require("chalk")),mt=m(require("inquirer")),En=require("commander"),G=m(require("fs-extra")),ae=m(require("path")),In=m(require("adm-zip"));_();A();B();F();var An=new En.Command("download");An.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("--version <version>","Download specific version (if available)").option("-f, --force","Overwrite existing directory without prompting").action(async(o,e)=>{try{await p.load();let n=new E(p.getApiConfig()),i=o;if(!i&&!e.nonInteractive){let u=await Jo(n);if(!u){t.info("Download cancelled");return}i=u}i||(t.error("Function ID required. Provide as argument or select interactively"),t.info(`Usage: ${O.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABCDE")}`),t.info(` or: ${O.default.cyan("sinch functions download")} (interactive selection)`),process.exit(1)),d.start("\u{1F4E1} Fetching function metadata...");let r=await n.getFunction(i);d.succeed("Function metadata loaded");let s=ae.join("functions",r.name),a=e.output||s,c=ae.resolve(a);if(await G.pathExists(c)){if(!e.force){let{overwrite:u}=await mt.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${a}' already exists. Overwrite?`,default:!1}]);if(!u){t.info("Download cancelled");return}}d.start("\u{1F5D1}\uFE0F Removing existing directory..."),await G.remove(c),d.succeed("Existing directory removed")}d.start("\u{1F4E5} Downloading function source code...");let l=await n.downloadFunction(i);if(d.succeed("Source code downloaded"),e.extract!==!1){d.start("\u{1F4E6} Extracting files..."),await G.ensureDir(c);let u=new In.default(l),g=u.getEntries();u.extractAllTo(c,!0),d.succeed(`\u{1F4E6} Extracted ${g.length} files`);let h=ae.join(c,"sinch-metadata.json"),S={functionId:r.id,name:r.name,runtime:r.runtime,status:r.status,downloadedAt:new Date().toISOString(),url:r.containerAppUrl,configuration:r.configuration};await G.writeJson(h,S,{spaces:2}),t.newline(),t.success("\u2705 Function downloaded successfully!"),t.newline(),t.info(`\u{1F4C1} Location: ${O.default.cyan(a)}`),t.info(`\u{1F4CB} Files: ${g.length} files extracted`);let w=ae.join(c,"sinch.json");await G.pathExists(w)&&t.info("\u{1F527} Config: sinch.json found"),t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 Navigate: ${O.default.cyan(`cd ${a}`)}`),t.info(` \u2022 Run locally: ${O.default.cyan("sinch functions dev")}`),t.info(` \u2022 Deploy changes: ${O.default.cyan("sinch functions deploy")}`)}else{let u=`${r.name}.zip`,g=e.output?ae.resolve(e.output):ae.resolve(u);d.start(`\u{1F4BE} Saving as ${u}...`),await G.writeFile(g,l),d.succeed("ZIP file saved"),t.newline(),t.success("\u2705 Function downloaded as ZIP!"),t.info(`\u{1F4C1} File: ${O.default.cyan(g)}`),t.info(`\u{1F4E6} Size: ${(l.length/1024).toFixed(2)} KB`)}}catch(n){d.stop(),n.message.includes("404")||n.message.includes("not found")?(t.error(`Function not found with ID: ${o}`),t.info("\u{1F4A1} List available functions with:"),t.info(` ${O.default.cyan("sinch functions list")}`),t.info("\u{1F4A1} Or use interactive selection:"),t.info(` ${O.default.cyan("sinch functions download")}`)):t.error(`Failed to download function: ${n.message}`),process.exit(1)}});async function Jo(o){try{d.start("\u{1F4CB} Loading functions...");let e=await o.listFunctions();if(d.stop(),!e.functions||e.functions.length===0)return t.warn("No functions found to download"),null;let n=e.functions.map(r=>({name:`${O.default.cyan(r.name.padEnd(20))} ${O.default.yellow(r.runtime.padEnd(8))} ${Mo(r.status)}`,value:r.id,short:r.name}));t.newline();let{selectedFunction:i}=await mt.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function to download:",choices:n,pageSize:15}]);return i}catch(e){throw d.stop(),e}}function Mo(o){return{Running:O.default.green("\u2705 Running"),Failed:O.default.red("\u274C Failed"),Pending:O.default.yellow("\u23F3 Pending"),Building:O.default.blue("\u{1F528} Building")}[o]||O.default.gray(o)}Rn.exports=An});var Fn=N((Sr,Dn)=>{"use strict";var jn=require("commander"),Wo=Dt(),Ho=Lt(),Go=Qt(),Yo=nn(),zo=cn(),Qo=yn(),Zo=vn(),Xo=Pn(),ei=Tn(),Y=new jn.Command("functions");Y.description("Manage Sinch Functions");Y.addCommand(Wo);Y.addCommand(Ho);Y.addCommand(Go);Y.addCommand(ei);Y.addCommand(Yo);Y.addCommand(zo);Y.addCommand(Qo);Y.addCommand(Zo);Y.addCommand(Xo);Dn.exports=Y});var xn=N((Er,_n)=>{"use strict";var On=require("commander"),M=m(require("chalk"));_();A();B();F();var te=new On.Command("templates");te.description("Browse and manage function templates");te.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(o,e)=>{try{await p.load();let n=new E(p.getApiConfig());d.start("Loading templates...");let i;if(o?i=await n.listRuntimeTemplates(o,e.category):i=await n.listAllTemplates(e.category),d.stop(),i.templates.length===0){t.info(`No templates found${o?` for ${o}`:""}${e.category?` in category ${e.category}`:""}`);return}let r=`Available Templates${o?` (${o})`:""}${e.category?` - ${e.category}`:""}`;if(t.title(r),e.detailed)i.templates.forEach((s,a)=>{a>0&&t.newline(),t.log(M.default.bold.blue(`${s.name}`)),t.log(` Runtime: ${s.runtime}`),t.log(` Category: ${s.category}`),t.log(` Description: ${s.description}`),s.tags&&s.tags.length>0&&t.log(` Tags: ${s.tags.map(c=>M.default.gray(c)).join(", ")}`),t.log(` Path: ${M.default.gray(s.path)}`)});else{let s=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"],s)}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){d.stop(),t.error(`Failed to list templates: ${n.message}`),process.exit(1)}});te.command("show").description("Show detailed template information").argument("<template>",'Template name in format "runtime/template-name"').action(async o=>{try{await p.load();let e=new E(p.getApiConfig());if(!o.includes("/"))throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');let n=o.split("/"),i=n[0],r=n[1];if(!i||!r)throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');d.start(`Loading template details for ${o}...`);let s=await e.getTemplateDetails(i,r);d.stop(),t.title(`Template: ${s.name}`),t.newline(),t.log(M.default.bold("Basic Information:")),t.log(` Runtime: ${s.runtime}`),t.log(` Category: ${s.category}`),t.log(` Description: ${s.description}`),s.tags&&s.tags.length>0&&t.log(` Tags: ${s.tags.map(a=>M.default.blue(a)).join(", ")}`),s.variables&&Object.keys(s.variables).length>0&&(t.newline(),t.log(M.default.bold("Template Variables:")),Object.entries(s.variables).forEach(([a,c])=>{t.log(` ${a}: ${M.default.gray(c)}`)})),s.files&&s.files.length>0&&(t.newline(),t.log(M.default.bold("Files:")),s.files.forEach(a=>{t.log(` ${M.default.gray("\u2022")} ${a}`)})),s.readmeContent&&(t.newline(),t.log(M.default.bold("README:")),s.readmeContent.split(`
73
+ `).slice(0,10).forEach(c=>{t.log(` ${M.default.gray(c)}`)}),s.readmeContent.split(`
74
+ `).length>10&&t.log(` ${M.default.gray("... (truncated)")}`)),t.newline(),t.info(`Use "sinch functions init --template ${o}" to create a function from this template`)}catch(e){d.stop(),t.error(`Failed to show template details: ${e.message}`),process.exit(1)}});te.command("node").description("List Node.js templates").option("-c, --category <category>","Filter by category").action(async o=>{let e=te.commands.find(n=>n.name()==="list");e&&await e.action("node",o)});te.command("csharp").description("List C# templates").option("-c, --category <category>","Filter by category").action(async o=>{let e=te.commands.find(n=>n.name()==="list");e&&await e.action("csharp",o)});te.command("python").description("List Python templates").option("-c, --category <category>","Filter by category").action(async o=>{let e=te.commands.find(n=>n.name()==="list");e&&await e.action("python",o)});_n.exports=te});var Bn=N((Tr,Un)=>{"use strict";var Ln=require("commander"),be=m(require("chalk")),Nn=m(require("inquirer"));A();B();F();var xe=new Ln.Command("voice");xe.description("Manage Sinch Voice applications and settings");xe.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(o,e)=>{try{await p.load(),await ht()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await ti(),i=e.appKey;if(!i){let r=p.getPublicCredentialInfo()?.applicationKey;r||(t.error('No default application key found. Run "sinch auth login" first.'),process.exit(1)),i=r,t.info(`Using default application: ${i}`)}if(!o){let{newUrl:r}=await Nn.default.prompt([{type:"input",name:"newUrl",message:"Enter new callback URL:",validate:s=>{if(!s)return"URL is required";try{return new URL(s),!0}catch{return"Please enter a valid URL"}}}]);o=r}d.start("Updating callback URL...");try{let r=await n.voice.applications.get(i),s={...r,capability:{...r.capability,voice:{...r.capability?.voice,webhooks:{...r.capability?.voice?.webhooks,url:o,method:"POST"}}}};await n.voice.applications.update(i,s),d.succeed("Callback URL updated successfully!"),t.newline(),t.info(`Application: ${r.displayName||i}`),t.info(`New callback URL: ${o}`),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(r){throw d.fail("Failed to update callback URL"),r}}catch(n){d.stop(),t.error(`Failed to update callback URL: ${n.message}`),process.exit(1)}});xe.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 o=>{try{await p.load(),await ht()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=await p.getApplicationCredentials();e||(t.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let n=o.appKey||e.applicationKey;if(t.info("\u{1F50D} Getting callback URLs..."),t.newline(),o.curl){let i=`${e.applicationKey}:${e.applicationSecret}`,r=Buffer.from(i).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(be.default.gray("```bash"));let s=`curl -X GET \\
75
75
  https://calling.api.sinch.com/calling/v1/applications/${n}/callbacks/urls \\
76
- -H "Authorization: Basic ${r}"`;t.info(ce.default.cyan(s)),t.info(ce.default.gray("```")),t.newline()}try{let{SinchClient:i}=require("@sinch/sdk-core"),r=new i({applicationKey:e.applicationKey,applicationSecret:e.applicationSecret});d.start("Fetching callback URLs...");let s=await r.voice.applications.getCallbackURLs({applicationkey:n});d.succeed("Callback URLs retrieved"),t.newline(),t.info("\u{1F4E5} Current Callback Configuration:"),t.info(JSON.stringify(s,null,2)),t.newline(),t.info("\u{1F50E} Parsed Values:"),t.info(` currentCallbacks.url: ${s?.url||"undefined"}`),t.info(` currentCallbacks.primary: ${s?.primary||"undefined"}`),t.info(` currentCallbacks.fallback: ${s?.fallback||"undefined"}`),t.info(` currentCallbacks.urls?.primary: ${s?.urls?.primary||"undefined"}`),t.info(` currentCallbacks.urls?.fallback: ${s?.urls?.fallback||"undefined"}`)}catch(i){d.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)}});le.command("callback-status").description("Show current callback URL for your Voice application").option("-a, --app-key <key>","Application key (if not provided, will show all)").action(async o=>{try{await p.load(),await Re()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=await Ye();if(d.start("Loading application settings..."),o.appKey){let n=await e.voice.applications.get(o.appKey);d.stop(),t.title(`Application: ${n.displayName||o.appKey}`),t.info(`App Key: ${n.key}`),t.info(`Callback URL: ${n.capability?.voice?.webhooks?.url||"Not set"}`),t.info(`Method: ${n.capability?.voice?.webhooks?.method||"Not set"}`)}else{let n=p.getPublicCredentialInfo()?.applicationKey;if(!n){t.error('No default application key found. Run "sinch auth login" first.');return}let i=await e.voice.applications.get(n);d.stop(),t.title("Voice Application Callback URLs (Default)"),t.newline(),t.info(`\u{1F4F1} ${i.displayName||"Unnamed"} (${i.key})`),t.info(` URL: ${i.capability?.voice?.webhooks?.url||ce.default.red("Not set")}`),t.info(` Method: ${i.capability?.voice?.webhooks?.method||"Not set"}`)}}catch(e){d.stop(),t.error(`Failed to get callback status: ${e.message}`),process.exit(1)}});le.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(o,e)=>{try{await p.load(),await Re()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await p.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 r=e.primaryOnly?{url:{primary:o}}:{url:{primary:o,fallback:o}},s=`${n.applicationKey}:${n.applicationSecret}`,a=Buffer.from(s).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(ce.default.gray("```bash"));let c=`curl -X POST \\
76
+ -H "Authorization: Basic ${r}"`;t.info(be.default.cyan(s)),t.info(be.default.gray("```")),t.newline()}try{let{SinchClient:i}=require("@sinch/sdk-core"),r=new i({applicationKey:e.applicationKey,applicationSecret:e.applicationSecret});d.start("Fetching callback URLs...");let s=await r.voice.applications.getCallbackURLs({applicationkey:n});d.succeed("Callback URLs retrieved"),t.newline(),t.info("\u{1F4E5} Current Callback Configuration:"),t.info(` currentCallbacks.primary: ${s?.primary||"undefined"}`),t.info(` currentCallbacks.fallback: ${s?.fallback||"undefined"}`)}catch(i){d.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)}});xe.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(o,e)=>{try{await p.load(),await ht()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await p.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 r=e.primaryOnly?{url:{primary:o}}:{url:{primary:o,fallback:o}},s=`${n.applicationKey}:${n.applicationSecret}`,a=Buffer.from(s).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(be.default.gray("```bash"));let c=`curl -X POST \\
77
77
  https://calling.api.sinch.com/calling/v1/applications/${i}/callbacks/urls \\
78
78
  -H "Authorization: Basic ${a}" \\
79
79
  -H "Content-Type: application/json" \\
80
- -d '${JSON.stringify(r,null,2)}'`;t.info(ce.default.cyan(c)),t.info(ce.default.gray("```")),t.newline();try{let{SinchClient:l}=require("@sinch/sdk-core"),u=new l({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret});t.info("\u{1F4E4} Request Body:"),t.info(JSON.stringify(r,null,2)),t.newline(),d.start("Sending update request..."),await u.voice.applications.updateCallbackURLs({applicationkey:i,updateCallbacksRequestBody:r}),d.succeed("Update request sent"),d.start("Waiting for changes to propagate..."),await new Promise(S=>setTimeout(S,5e3)),d.start("Verifying update...");let g=await u.voice.applications.getCallbackURLs({applicationkey:i});d.succeed("Verification complete"),t.newline(),t.info("\u{1F4E5} Current Callback URLs:"),t.info(JSON.stringify(g,null,2));let h=g?.url||g?.primary||g?.urls?.primary;h===o?(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: "+o),t.info("Actual: "+(typeof h=="object"?JSON.stringify(h):h||"not found")),t.newline(),t.info("\u{1F50D} Debug - Response structure:"),t.info(" typeof currentCallbacks: "+typeof g),t.info(" currentCallbacks.url: "+(g?.url||"undefined")),t.info(" currentCallbacks.primary: "+(g?.primary||"undefined")),t.info(" currentCallbacks.urls?.primary: "+(g?.urls?.primary||"undefined")))}catch(l){d.fail("Update failed"),t.error(`Error: ${l.message}`),e.debug&&(t.newline(),t.info("Full error details:"),t.info(JSON.stringify(l,null,2)))}}catch(n){t.error(`Command failed: ${n.message}`),process.exit(1)}});le.command("test-webhook").description("Test webhook connectivity to your callback URL").option("-u, --url <url>","URL to test (defaults to configured callback URL)").action(async o=>{try{await p.load();let e=o.url;if(!e){await Re()||(t.error('Not authenticated or no URL provided. Run "sinch auth login" first or use --url option.'),process.exit(1));let n=await Ye();d.start("Getting callback URL...");let i=p.getPublicCredentialInfo()?.applicationKey;i||(t.error("No default application key found"),process.exit(1));let r=await n.voice.applications.get(i);d.stop(),e=r.capability?.voice?.webhooks?.url,e||(t.error("No callback URL configured. Set one with: sinch voice callback-url"),process.exit(1))}d.start(`Testing webhook at ${e}...`);try{let n=await fetch(e,{method:"GET",timeout:1e4});n.ok?(d.succeed("Webhook is responding!"),t.info(`Status: ${n.status} ${n.statusText}`)):(d.warn("Webhook responded with error"),t.warn(`Status: ${n.status} ${n.statusText}`))}catch(n){d.fail("Webhook test failed"),n.code==="ECONNREFUSED"?(t.error("Connection refused - is your function running?"),t.info("\u{1F4A1} Try: sinch functions dev")):t.error(`Error: ${n.message}`)}}catch(e){d.stop(),t.error(`Webhook test failed: ${e.message}`),process.exit(1)}});async function Re(){return await p.hasCredentials()}async function Ye(){return await p.createSinchClient()}Bn.exports=le});var Jn=N((Or,Mn)=>{"use strict";var qn=require("commander"),oe=m(require("keytar")),R=m(require("chalk"));K();var wt=m(require("inquirer")),ue="sinch-functions-cli",$e=new qn.Command("secrets");$e.description("Manage secure secrets in OS keychain").addHelpText("after",`
80
+ -d '${JSON.stringify(r,null,2)}'`;t.info(be.default.cyan(c)),t.info(be.default.gray("```")),t.newline();try{let{SinchClient:l}=require("@sinch/sdk-core"),u=new l({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret});t.info("\u{1F4E4} Request Body:"),t.info(JSON.stringify(r,null,2)),t.newline(),d.start("Sending update request..."),await u.voice.applications.updateCallbackURLs({applicationkey:i,updateCallbacksRequestBody:r}),d.succeed("Update request sent"),d.start("Waiting for changes to propagate..."),await new Promise(S=>setTimeout(S,5e3)),d.start("Verifying update...");let g=await u.voice.applications.getCallbackURLs({applicationkey:i});d.succeed("Verification complete"),t.newline(),t.info("\u{1F4E5} Current Callback URLs:"),t.info(JSON.stringify(g,null,2));let h=g?.url||g?.primary||g?.urls?.primary;h===o?(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: "+o),t.info("Actual: "+(typeof h=="object"?JSON.stringify(h):h||"not found")),t.newline(),t.info("\u{1F50D} Debug - Response structure:"),t.info(" typeof currentCallbacks: "+typeof g),t.info(" currentCallbacks.url: "+(g?.url||"undefined")),t.info(" currentCallbacks.primary: "+(g?.primary||"undefined")),t.info(" currentCallbacks.urls?.primary: "+(g?.urls?.primary||"undefined")))}catch(l){d.fail("Update failed"),t.error(`Error: ${l.message}`),e.debug&&(t.newline(),t.info("Full error details:"),t.info(JSON.stringify(l,null,2)))}}catch(n){t.error(`Command failed: ${n.message}`),process.exit(1)}});async function ht(){return await p.hasCredentials()}async function ti(){return await p.createSinchClient()}Un.exports=xe});var Vn=N((Dr,qn)=>{"use strict";var Kn=require("commander"),oe=m(require("keytar")),R=m(require("chalk"));B();var yt=m(require("inquirer")),ce="sinch-functions-cli",Se=new Kn.Command("secrets");Se.description("Manage secure secrets in OS keychain").addHelpText("after",`
81
81
  Examples:
82
82
  ${R.default.cyan("sinch secrets list")} List all custom secrets
83
83
  ${R.default.cyan("sinch secrets add API_KEY abc123")} Add or update a secret
@@ -88,46 +88,43 @@ Note: Secrets are stored securely in your OS keychain:
88
88
  - Windows: Credential Manager
89
89
  - macOS: Keychain
90
90
  - Linux: Secret Service API
91
- `);$e.command("list").description("List all custom secrets (keys only)").action(async()=>{try{let e=(await oe.default.findCredentials(ue)).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(` ${R.default.cyan("sinch secrets add <KEY> <VALUE>")}`);return}t.info(R.default.bold("Custom Secrets:")),t.info(""),e.forEach(n=>{t.info(` \u{1F510} ${R.default.cyan(n)}`)}),t.info(""),t.info(`Total: ${e.length} secret(s)`)}catch(o){t.error("Failed to list secrets:",o.message),process.exit(1)}});$e.command("add <key> <value>").description("Add or update a secret in OS keychain").action(async(o,e)=>{try{o.match(/^[A-Z0-9_]+$/)||(t.error("Secret key must be uppercase letters, numbers, and underscores only"),t.info(`Example: ${R.default.cyan("API_KEY")}, ${R.default.cyan("DATABASE_PASSWORD")}`),process.exit(1));let n=`custom-${o}`,r=await oe.default.getPassword(ue,n)!==null;await oe.default.setPassword(ue,n,e),r?t.success(`\u2705 Updated secret: ${R.default.cyan(o)}`):t.success(`\u2705 Added secret: ${R.default.cyan(o)}`),t.info(""),t.info("\u{1F4DD} To use in your function:"),t.info(` 1. Add ${R.default.cyan(o+"=")} to your .env file (leave value empty)`),t.info(` 2. Access via ${R.default.cyan("process.env."+o)} 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)}});$e.command("get <key>").description("Get a specific secret value").option("--show","Show the actual value (be careful!)").action(async(o,e)=>{try{let n=`custom-${o}`,i=await oe.default.getPassword(ue,n);i||(t.error(`Secret not found: ${R.default.cyan(o)}`),t.info(""),t.info("\u{1F4A1} Available secrets:"),t.info(` Run ${R.default.cyan("sinch secrets list")} to see all secrets`),process.exit(1)),t.info(`Secret: ${R.default.cyan(o)}`),e.show?(t.warn("\u26A0\uFE0F Showing secret value - be careful not to expose it!"),t.info(`Value: ${i}`)):(t.info(`Value: ${R.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)}});$e.command("delete <key>").alias("remove").alias("rm").description("Remove a secret from OS keychain").option("-f, --force","Skip confirmation").action(async(o,e)=>{try{let n=`custom-${o}`;if(await oe.default.getPassword(ue,n)||(t.error(`Secret not found: ${R.default.cyan(o)}`),process.exit(1)),!e.force&&!(await wt.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete secret '${o}'?`,default:!1}])).confirm){t.info("Cancelled");return}await oe.default.deletePassword(ue,n)?t.success(`\u2705 Deleted secret: ${R.default.cyan(o)}`):(t.error("Failed to delete secret"),process.exit(1))}catch(n){t.error("Failed to delete secret:",n.message),process.exit(1)}});$e.command("clear").description("Remove ALL custom secrets (use with caution!)").option("-f, --force","Skip confirmation").action(async o=>{try{let n=(await oe.default.findCredentials(ue)).filter(r=>r.account&&r.account.startsWith("custom-"));if(n.length===0){t.info("No custom secrets to clear");return}if(!o.force&&(t.warn(`\u26A0\uFE0F This will delete ${n.length} custom secret(s)`),!(await wt.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 r of n)await oe.default.deletePassword(ue,r.account)&&i++;t.success(`\u2705 Deleted ${i} custom secret(s)`)}catch(e){t.error("Failed to clear secrets:",e.message),process.exit(1)}});Mn.exports=$e});var bt=require("commander"),f=m(require("chalk")),de=m(require("fs-extra")),ze=m(require("path")),Ct=m(require("os")),Wn=require("child_process");var me=m(require("fs")),Ze=m(require("path")),vt=require("child_process"),ge=m(require("chalk")),Xn=18e5,eo="https://registry.npmjs.org/@sinch/cli";function to(){if(process.platform!=="win32")try{if(me.default.existsSync("/.dockerenv"))return!0;let o=me.default.readFileSync("/proc/1/cgroup","utf8");return o.includes("docker")||o.includes("containerd")}catch{return!1}return!!process.env.DOCKER_CONTAINER}function no(){return!!process.env.CI}function oo(){return to()||no()}function io(o){return o.includes("-dev.")?"dev":parseInt(o.split(".")[0]||"0")>=1?"latest":"beta"}function ro(o){try{if(!me.default.existsSync(o))return!0;let e=parseInt(me.default.readFileSync(o,"utf8"));return Date.now()-e>Xn}catch{return!0}}function so(o,e){let n=o.replace(/^v/,"").split("-")[0]||"0.0.0",i=e.replace(/^v/,"").split("-")[0]||"0.0.0",r=n.split(".").map(a=>parseInt(a)||0),s=i.split(".").map(a=>parseInt(a)||0);for(let a=0;a<3;a++){let c=r[a]||0,l=s[a]||0;if(l>c)return!0;if(l<c)return!1}if(o.includes("-dev.")&&e.includes("-dev.")){let a=parseInt(o.split("-dev.")[1]||"0");return parseInt(e.split("-dev.")[1]||"0")>a}return!1}async function ao(o){try{let e=await fetch(eo,{signal:AbortSignal.timeout(3e3)});return e.ok&&(await e.json())["dist-tags"]?.[o]||null}catch{return null}}function co(o){try{console.log(ge.default.cyan(`
92
- \u{1F504} Updating @sinch/cli from ${o} channel...`));let n=`npm install -g ${process.platform==="win32"?"--force":""} @sinch/cli@${o}`.trim();return(0,vt.execSync)(n,{stdio:"inherit",timeout:3e4}),console.log(ge.default.green(`\u2705 Update completed successfully!
93
- `)),!0}catch(e){return console.log(ge.default.yellow(`\u26A0\uFE0F Auto-update failed: ${e.message}`)),console.log(ge.default.gray(`You can manually update with: npm install -g @sinch/cli@${o}
94
- `)),!1}}async function lo(o,e){let n=Qe().version,i=io(n);try{let r=await ao(i);if(!r)return;so(n,r)&&(console.log(ge.default.yellow(`
95
- \u{1F4E6} Update available: ${n} \u2192 ${r}`)),i==="dev"||i==="beta"?co(i):console.log(ge.default.cyan(`Run: npm install -g @sinch/cli@${i}
96
- `))),me.default.mkdirSync(o,{recursive:!0}),me.default.writeFileSync(e,Date.now().toString())}catch{}}function $t(){if(oo())return;let o=Ze.default.join(require("os").homedir(),".sinch"),e=Ze.default.join(o,".last-update-check");ro(e)&&lo(o,e).catch(()=>{})}process.env.NODE_NO_WARNINGS||(process.env.NODE_NO_WARNINGS="1",process.removeAllListeners("warning"));$t();var ii=Qe(),ri=Ln(),si=Nn(),ai=Vn(),ci=Jn(),z=new bt.Command;z.name("sinch").description("Sinch Functions - Serverless function platform for voice applications").version(ii.version,"-V, --version","output the version number").helpOption("-h, --help","Display help for command");z.addCommand(ri);z.addCommand(si);z.addCommand(ai);z.addCommand(ci);var Ue=new bt.Command("auth");Ue.description("Authentication management for Sinch Voice API");Ue.command("login").description("Authenticate with Sinch Voice API").option("-f, --credentials-file <path>","Path to credentials JSON file").action(async o=>{let{config:e}=(I(),O(he)),n=require("inquirer");try{if(await e.load(),o.credentialsFile){console.log(f.default.blue(`
91
+ `);Se.command("list").description("List all custom secrets (keys only)").action(async()=>{try{let e=(await oe.default.findCredentials(ce)).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(` ${R.default.cyan("sinch secrets add <KEY> <VALUE>")}`);return}t.info(R.default.bold("Custom Secrets:")),t.info(""),e.forEach(n=>{t.info(` \u{1F510} ${R.default.cyan(n)}`)}),t.info(""),t.info(`Total: ${e.length} secret(s)`)}catch(o){t.error("Failed to list secrets:",o.message),process.exit(1)}});Se.command("add <key> <value>").description("Add or update a secret in OS keychain").action(async(o,e)=>{try{o.match(/^[A-Z0-9_]+$/)||(t.error("Secret key must be uppercase letters, numbers, and underscores only"),t.info(`Example: ${R.default.cyan("API_KEY")}, ${R.default.cyan("DATABASE_PASSWORD")}`),process.exit(1));let n=`custom-${o}`,r=await oe.default.getPassword(ce,n)!==null;await oe.default.setPassword(ce,n,e),r?t.success(`\u2705 Updated secret: ${R.default.cyan(o)}`):t.success(`\u2705 Added secret: ${R.default.cyan(o)}`),t.info(""),t.info("\u{1F4DD} To use in your function:"),t.info(` 1. Add ${R.default.cyan(o+"=")} to your .env file (leave value empty)`),t.info(` 2. Access via ${R.default.cyan("process.env."+o)} 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)}});Se.command("get <key>").description("Get a specific secret value").option("--show","Show the actual value (be careful!)").action(async(o,e)=>{try{let n=`custom-${o}`,i=await oe.default.getPassword(ce,n);i||(t.error(`Secret not found: ${R.default.cyan(o)}`),t.info(""),t.info("\u{1F4A1} Available secrets:"),t.info(` Run ${R.default.cyan("sinch secrets list")} to see all secrets`),process.exit(1)),t.info(`Secret: ${R.default.cyan(o)}`),e.show?(t.warn("\u26A0\uFE0F Showing secret value - be careful not to expose it!"),t.info(`Value: ${i}`)):(t.info(`Value: ${R.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)}});Se.command("delete <key>").alias("remove").alias("rm").description("Remove a secret from OS keychain").option("-f, --force","Skip confirmation").action(async(o,e)=>{try{let n=`custom-${o}`;if(await oe.default.getPassword(ce,n)||(t.error(`Secret not found: ${R.default.cyan(o)}`),process.exit(1)),!e.force&&!(await yt.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete secret '${o}'?`,default:!1}])).confirm){t.info("Cancelled");return}await oe.default.deletePassword(ce,n)?t.success(`\u2705 Deleted secret: ${R.default.cyan(o)}`):(t.error("Failed to delete secret"),process.exit(1))}catch(n){t.error("Failed to delete secret:",n.message),process.exit(1)}});Se.command("clear").description("Remove ALL custom secrets (use with caution!)").option("-f, --force","Skip confirmation").action(async o=>{try{let n=(await oe.default.findCredentials(ce)).filter(r=>r.account&&r.account.startsWith("custom-"));if(n.length===0){t.info("No custom secrets to clear");return}if(!o.force&&(t.warn(`\u26A0\uFE0F This will delete ${n.length} custom secret(s)`),!(await yt.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 r of n)await oe.default.deletePassword(ce,r.account)&&i++;t.success(`\u2705 Deleted ${i} custom secret(s)`)}catch(e){t.error("Failed to clear secrets:",e.message),process.exit(1)}});qn.exports=Se});var wt=require("commander"),f=m(require("chalk")),le=m(require("fs-extra")),He=m(require("path")),Ct=m(require("os")),Jn=require("child_process");var pe=m(require("fs")),Ye=m(require("path")),ze=m(require("chalk")),Qn=18e5,Zn="https://registry.npmjs.org/@sinch/cli";function Xn(){if(process.platform!=="win32")try{if(pe.default.existsSync("/.dockerenv"))return!0;let o=pe.default.readFileSync("/proc/1/cgroup","utf8");return o.includes("docker")||o.includes("containerd")}catch{return!1}return!!process.env.DOCKER_CONTAINER}function eo(){return!!process.env.CI}function to(){return Xn()||eo()}function no(o){return o.includes("-dev.")?"dev":parseInt(o.split(".")[0]||"0")>=1?"latest":"beta"}function oo(o){try{if(!pe.default.existsSync(o))return!0;let e=parseInt(pe.default.readFileSync(o,"utf8"));return Date.now()-e>Qn}catch{return!0}}function io(o,e){let n=o.replace(/^v/,"").split("-")[0]||"0.0.0",i=e.replace(/^v/,"").split("-")[0]||"0.0.0",r=n.split(".").map(a=>parseInt(a)||0),s=i.split(".").map(a=>parseInt(a)||0);for(let a=0;a<3;a++){let c=r[a]||0,l=s[a]||0;if(l>c)return!0;if(l<c)return!1}if(o.includes("-dev.")&&e.includes("-dev.")){let a=parseInt(o.split("-dev.")[1]||"0");return parseInt(e.split("-dev.")[1]||"0")>a}return!1}async function ro(o){try{let e=await fetch(Zn,{signal:AbortSignal.timeout(3e3)});return e.ok&&(await e.json())["dist-tags"]?.[o]||null}catch{return null}}async function so(o,e){let n=Ge().version,i=no(n);try{let r=await ro(i);if(!r)return;io(n,r)&&(console.log(ze.default.yellow(`
92
+ \u{1F4E6} Update available: ${n} \u2192 ${r}`)),console.log(ze.default.cyan(`Run: npm install -g @sinch/cli@${i}
93
+ `))),pe.default.mkdirSync(o,{recursive:!0}),pe.default.writeFileSync(e,Date.now().toString())}catch{}}function St(){if(to())return;let o=Ye.default.join(require("os").homedir(),".sinch"),e=Ye.default.join(o,".last-update-check");oo(e)&&so(o,e).catch(()=>{})}process.env.NODE_NO_WARNINGS||(process.env.NODE_NO_WARNINGS="1",process.removeAllListeners("warning"));St();var ni=Ge(),oi=Fn(),ii=xn(),ri=Bn(),si=Vn(),z=new wt.Command;z.name("sinch").description("Sinch Functions - Serverless function platform for voice applications").version(ni.version,"-V, --version","output the version number").helpOption("-h, --help","Display help for command");z.addCommand(oi);z.addCommand(ii);z.addCommand(ri);z.addCommand(si);var Le=new wt.Command("auth");Le.description("Authentication management for Sinch Voice API");Le.command("login").description("Authenticate with Sinch Voice API").option("-f, --credentials-file <path>","Path to credentials JSON file").action(async o=>{let{config:e}=(A(),D(fe)),n=require("inquirer");try{if(await e.load(),o.credentialsFile){console.log(f.default.blue(`
97
94
  \u{1F510} Sinch Voice API Authentication`)),console.log(f.default.gray(`Loading credentials from: ${o.credentialsFile}
98
- `)),de.default.existsSync(o.credentialsFile)||(console.error(f.default.red(`\u274C Credentials file not found: ${o.credentialsFile}`)),process.exit(1));try{let l=de.default.readFileSync(o.credentialsFile,"utf-8"),u=JSON.parse(l),h=["projectId","keyId","keySecret","applicationKey","applicationSecret"].filter(T=>!u[T]);h.length>0&&(console.error(f.default.red(`\u274C Missing required fields in credentials file: ${h.join(", ")}`)),console.error(f.default.gray(`
99
- Expected format:`)),console.error(f.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 S={projectId:u.projectId,keyId:u.keyId,keySecret:u.keySecret,applicationKey:u.applicationKey,applicationSecret:u.applicationSecret},{spinner:w}=(j(),O(Pe));w.start("Verifying credentials...");try{w.update("Obtaining OAuth access token...");let{SinchAPI:T}=(L(),O(De)),$=await new T({apiUrl:e.get("apiUrl"),projectId:S.projectId,credentials:e._credentials}).authenticateOAuth(S.keyId,S.keySecret);w.succeed("OAuth token obtained successfully!"),w.start("Testing Voice API connection...");let{SinchClient:C}=require("@sinch/sdk-core");await new C({applicationKey:S.applicationKey,applicationSecret:S.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:S.applicationKey}),w.succeed("Credentials verified successfully!"),await e._credentials.storeOAuthToken($),await e._credentials.store(S),console.log(f.default.green(`
100
- \u2705 Authentication successful!`)),console.log(f.default.gray("All credentials saved securely. You can now:")),console.log(" \u2022 Update callback URLs with: sinch voice callback-url <url>"),console.log(" \u2022 View your applications with: sinch voice apps"),console.log(" \u2022 Deploy functions with live webhook testing"),console.log(" \u2022 Buy numbers and manage project resources"),console.log(""),console.log(f.default.blue("\u{1F512} Security:")),console.log(f.default.gray(" \u2022 Secrets stored in OS credential manager (Windows/macOS/Linux)")),console.log(f.default.gray(" \u2022 Non-sensitive data in ~/.sinch/config.json"));return}catch(T){w.fail(f.default.red("Authentication failed")),console.error(f.default.red(`
95
+ `)),le.default.existsSync(o.credentialsFile)||(console.error(f.default.red(`\u274C Credentials file not found: ${o.credentialsFile}`)),process.exit(1));try{let l=le.default.readFileSync(o.credentialsFile,"utf-8"),u=JSON.parse(l),h=["projectId","keyId","keySecret","applicationKey","applicationSecret"].filter(T=>!u[T]);h.length>0&&(console.error(f.default.red(`\u274C Missing required fields in credentials file: ${h.join(", ")}`)),console.error(f.default.gray(`
96
+ Expected format:`)),console.error(f.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 S={projectId:u.projectId,keyId:u.keyId,keySecret:u.keySecret,applicationKey:u.applicationKey,applicationSecret:u.applicationSecret},{spinner:w}=(F(),D(ke));w.start("Verifying credentials...");try{w.update("Obtaining OAuth access token...");let{SinchAPI:T}=(_(),D($e)),$=await new T({apiUrl:e.get("apiUrl"),projectId:S.projectId,credentials:e._credentials}).authenticateOAuth(S.keyId,S.keySecret);w.succeed("OAuth token obtained successfully!"),w.start("Testing Voice API connection...");let{SinchClient:b}=require("@sinch/sdk-core");await new b({applicationKey:S.applicationKey,applicationSecret:S.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:S.applicationKey}),w.succeed("Credentials verified successfully!"),await e._credentials.storeOAuthToken($),await e._credentials.store(S),console.log(f.default.green(`
97
+ \u2705 Authentication successful!`)),console.log(f.default.gray("All credentials saved securely. You can now:")),console.log(" \u2022 Update callback URLs with: sinch voice callback-url <url>"),console.log(" \u2022 Deploy functions with live webhook testing"),console.log(" \u2022 Buy numbers and manage project resources"),console.log(""),console.log(f.default.blue("\u{1F512} Security:")),console.log(f.default.gray(" \u2022 Secrets stored in OS credential manager (Windows/macOS/Linux)")),console.log(f.default.gray(" \u2022 Non-sensitive data in ~/.sinch/config.json"));return}catch(T){w.fail(f.default.red("Authentication failed")),console.error(f.default.red(`
101
98
  \u274C ${T.message||"Failed to authenticate with provided credentials"}`)),process.exit(1)}}catch(l){console.error(f.default.red(`\u274C Failed to parse credentials file: ${l.message}`)),process.exit(1)}}let i=await e.getCredentials(),r=e.getPublicCredentialInfo();console.log(f.default.blue(`
102
99
  \u{1F510} Sinch Voice API Authentication`)),console.log(i?f.default.gray(`Found existing credentials. Press Enter to reuse them or enter new values.
103
100
  `):f.default.gray(`Enter your Sinch credentials to manage voice applications and callbacks
104
- `));let s=await n.prompt([{type:"input",name:"projectId",message:"Project ID (from Sinch Dashboard):",default:r?.projectId||void 0,validate:l=>!l&&r?.projectId?!0:l.length>0||"Project ID is required"},{type:"input",name:"keyId",message:"Key ID (from Project \u2192 Access Keys):",default:r?.keyId||void 0,validate:l=>!l&&r?.keyId?!0:l.length>0||"Key ID is required"},{type:"password",name:"keySecret",message:"Key Secret:",default:i?.keySecret||void 0,validate:l=>!l&&i?.keySecret?!0:l.length>0||"Key Secret is required"},{type:"input",name:"applicationKey",message:"Voice Application Key:",default:r?.applicationKey||void 0,validate:l=>!l&&r?.applicationKey?!0:l.length>0||"Application Key is required"},{type:"password",name:"applicationSecret",message:"Voice Application Secret:",default:i?.applicationSecret||void 0,validate:l=>!l&&i?.applicationSecret?!0:l.length>0||"Application Secret is required"}]),a={projectId:s.projectId||r?.projectId,keyId:s.keyId||r?.keyId,keySecret:s.keySecret||i?.keySecret,applicationKey:s.applicationKey||r?.applicationKey,applicationSecret:s.applicationSecret||i?.applicationSecret},{spinner:c}=(j(),O(Pe));c.start("Verifying credentials...");try{c.update("Obtaining OAuth access token...");let{SinchAPI:l}=(L(),O(De)),g=await new l({apiUrl:e.get("apiUrl"),projectId:a.projectId||e.get("projectId"),credentials:e._credentials}).authenticateOAuth(a.keyId,a.keySecret);c.succeed("OAuth token obtained successfully!"),c.start("Testing Voice API connection...");let{SinchClient:h}=require("@sinch/sdk-core");await new h({applicationKey:a.applicationKey,applicationSecret:a.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:a.applicationKey}),c.succeed("Credentials verified successfully!"),await e._credentials.storeOAuthToken(g),await e._credentials.store(a),console.log(f.default.green(`
105
- \u2705 Authentication successful!`)),console.log(f.default.gray("All credentials saved securely. You can now:")),console.log(" \u2022 Update callback URLs with: sinch voice callback-url <url>"),console.log(" \u2022 View your applications with: sinch voice apps"),console.log(" \u2022 Deploy functions with live webhook testing"),console.log(" \u2022 Buy numbers and manage project resources"),console.log(""),console.log(f.default.blue("\u{1F512} Security:")),console.log(f.default.gray(" \u2022 Secrets stored in OS credential manager (Windows/macOS/Linux)")),console.log(f.default.gray(" \u2022 Non-sensitive data in ~/.sinch/config.json"))}catch(l){c.fail("Authentication failed"),console.error(f.default.red(`
101
+ `));let s=await n.prompt([{type:"input",name:"projectId",message:"Project ID (from Sinch Dashboard):",default:r?.projectId||void 0,validate:l=>!l&&r?.projectId?!0:l.length>0||"Project ID is required"},{type:"input",name:"keyId",message:"Key ID (from Project \u2192 Access Keys):",default:r?.keyId||void 0,validate:l=>!l&&r?.keyId?!0:l.length>0||"Key ID is required"},{type:"password",name:"keySecret",message:"Key Secret:",default:i?.keySecret||void 0,validate:l=>!l&&i?.keySecret?!0:l.length>0||"Key Secret is required"},{type:"input",name:"applicationKey",message:"Voice Application Key:",default:r?.applicationKey||void 0,validate:l=>!l&&r?.applicationKey?!0:l.length>0||"Application Key is required"},{type:"password",name:"applicationSecret",message:"Voice Application Secret:",default:i?.applicationSecret||void 0,validate:l=>!l&&i?.applicationSecret?!0:l.length>0||"Application Secret is required"}]),a={projectId:s.projectId||r?.projectId,keyId:s.keyId||r?.keyId,keySecret:s.keySecret||i?.keySecret,applicationKey:s.applicationKey||r?.applicationKey,applicationSecret:s.applicationSecret||i?.applicationSecret},{spinner:c}=(F(),D(ke));c.start("Verifying credentials...");try{c.update("Obtaining OAuth access token...");let{SinchAPI:l}=(_(),D($e)),g=await new l({apiUrl:e.get("apiUrl"),projectId:a.projectId||e.get("projectId"),credentials:e._credentials}).authenticateOAuth(a.keyId,a.keySecret);c.succeed("OAuth token obtained successfully!"),c.start("Testing Voice API connection...");let{SinchClient:h}=require("@sinch/sdk-core");await new h({applicationKey:a.applicationKey,applicationSecret:a.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:a.applicationKey}),c.succeed("Credentials verified successfully!"),await e._credentials.storeOAuthToken(g),await e._credentials.store(a),console.log(f.default.green(`
102
+ \u2705 Authentication successful!`)),console.log(f.default.gray("All credentials saved securely. You can now:")),console.log(" \u2022 Update callback URLs with: sinch voice callback-url <url>"),console.log(" \u2022 Deploy functions with live webhook testing"),console.log(" \u2022 Buy numbers and manage project resources"),console.log(""),console.log(f.default.blue("\u{1F512} Security:")),console.log(f.default.gray(" \u2022 Secrets stored in OS credential manager (Windows/macOS/Linux)")),console.log(f.default.gray(" \u2022 Non-sensitive data in ~/.sinch/config.json"))}catch(l){c.fail("Authentication failed"),console.error(f.default.red(`
106
103
  \u274C Error: ${l.message}`)),console.log(f.default.yellow(`
107
- \u{1F4A1} Please check your credentials and try again`)),process.exit(1)}}catch(i){console.error(f.default.red(`Authentication failed: ${i.message}`)),process.exit(1)}});Ue.command("status").description("Show current authentication status").action(async()=>{let{config:o}=(I(),O(he));try{await o.load();let e=await o.hasCredentials(),n=o.getPublicCredentialInfo(),i=await o._credentials.retrieveOAuthToken();if(console.log(f.default.blue(`
108
- \u{1F510} Authentication Status`)),e&&n){if(console.log(f.default.green("\u2705 Authenticated")),console.log(` Project ID: ${n.projectId}`),console.log(` Key ID: ${n.keyId}`),console.log(` Application Key: ${n.applicationKey}`),console.log(f.default.gray(" (Secrets stored securely in OS keychain)")),i){let s=i.isExpired(),a=new Date(i.expires_at),c=Math.round((a.getTime()-new Date().getTime())/1e3/60);console.log(s?f.default.yellow(" OAuth Token: Expired (will auto-refresh)"):f.default.green(` OAuth Token: Valid (expires in ${c} minutes)`))}else console.log(f.default.yellow(" OAuth Token: Not found"));let{spinner:r}=(j(),O(Pe));r.start("Testing connection...");try{let s=await o.getApplicationCredentials();if(!s){r.fail("No application credentials found");return}let{SinchClient:a}=require("@sinch/sdk-core");await new a({applicationKey:s.applicationKey,applicationSecret:s.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:s.applicationKey}),r.succeed("Connection active")}catch{r.fail("Connection failed"),console.log(f.default.yellow("\u26A0\uFE0F Credentials may be expired or invalid"))}}else console.log(f.default.red("\u274C Not authenticated")),console.log(f.default.gray('Run "sinch auth login" to authenticate'))}catch(e){console.error(f.default.red(`Failed to check status: ${e.message}`)),process.exit(1)}});Ue.command("logout").description("Clear stored authentication credentials").action(async()=>{let{config:o}=(I(),O(he)),e=require("inquirer");try{(await e.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to logout and clear credentials?",default:!1}])).confirm?(await o.load(),await o.clearCredentials(),console.log(f.default.green("\u2705 Logged out successfully")),console.log(f.default.gray("All credentials cleared from secure storage"))):console.log(f.default.gray("Logout cancelled"))}catch(n){console.error(f.default.red(`Logout failed: ${n.message}`)),process.exit(1)}});z.addCommand(Ue);z.command("config").description("Configuration management").option("--set <key=value>","Set configuration value").option("--get <key>","Get configuration value").option("--list","List all configuration values").action(async o=>{let{config:e}=(I(),O(he));try{if(await e.load(),o.set){let[n,i]=o.set.split("=");(!n||!i)&&(console.error(f.default.red("Invalid format. Use: --set key=value")),process.exit(1)),e.set(n,i),await e.save(),console.log(f.default.green(`\u2705 Set ${n} = ${i}`))}else if(o.get){let n=e.get(o.get);console.log(n!==null?n:f.default.gray("(not set)"))}else if(o.list){console.log(f.default.blue(`
104
+ \u{1F4A1} Please check your credentials and try again`)),process.exit(1)}}catch(i){console.error(f.default.red(`Authentication failed: ${i.message}`)),process.exit(1)}});Le.command("status").description("Show current authentication status").action(async()=>{let{config:o}=(A(),D(fe));try{await o.load();let e=await o.hasCredentials(),n=o.getPublicCredentialInfo();if(console.log(f.default.blue(`
105
+ \u{1F510} Authentication Status`)),e&&n){console.log(f.default.green("\u2705 Authenticated")),console.log(` Project ID: ${n.projectId}`),console.log(` Key ID: ${n.keyId}`),console.log(` Application Key: ${n.applicationKey}`),console.log(f.default.gray(" (Secrets stored securely in OS keychain)"));try{let r=(_(),D($e)).default,s=o.getApiConfig();await new r(s).authenticate(),console.log(f.default.green(" OAuth Token: Valid"))}catch{console.log(f.default.yellow(" OAuth Token: Expired or invalid (will auto-refresh on next API call)"))}let{spinner:i}=(F(),D(ke));i.start("Testing connection...");try{let r=await o.getApplicationCredentials();if(!r){i.fail("No application credentials found");return}let{SinchClient:s}=require("@sinch/sdk-core");await new s({applicationKey:r.applicationKey,applicationSecret:r.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:r.applicationKey}),i.succeed("Connection active")}catch{i.fail("Connection failed"),console.log(f.default.yellow("\u26A0\uFE0F Credentials may be expired or invalid"))}}else console.log(f.default.red("\u274C Not authenticated")),console.log(f.default.gray('Run "sinch auth login" to authenticate'))}catch(e){console.error(f.default.red(`Failed to check status: ${e.message}`)),process.exit(1)}});Le.command("logout").description("Clear stored authentication credentials").action(async()=>{let{config:o}=(A(),D(fe)),e=require("inquirer");try{(await e.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to logout and clear credentials?",default:!1}])).confirm?(await o.load(),await o.clearCredentials(),console.log(f.default.green("\u2705 Logged out successfully")),console.log(f.default.gray("All credentials cleared from secure storage"))):console.log(f.default.gray("Logout cancelled"))}catch(n){console.error(f.default.red(`Logout failed: ${n.message}`)),process.exit(1)}});z.addCommand(Le);z.command("config").description("Configuration management").option("--set <key=value>","Set configuration value").option("--get <key>","Get configuration value").option("--list","List all configuration values").action(async o=>{let{config:e}=(A(),D(fe));try{if(await e.load(),o.set){let[n,i]=o.set.split("=");(!n||!i)&&(console.error(f.default.red("Invalid format. Use: --set key=value")),process.exit(1)),e.set(n,i),await e.save(),console.log(f.default.green(`\u2705 Set ${n} = ${i}`))}else if(o.get){let n=e.get(o.get);console.log(n!==null?n:f.default.gray("(not set)"))}else if(o.list){console.log(f.default.blue(`
109
106
  \u{1F4CB} Configuration:`));let n=e.getApiConfig();Object.entries(n).forEach(([i,r])=>{console.log(` ${i}: ${r}`)})}else console.log(f.default.blue(`
110
107
  \u2699\uFE0F Configuration Management`)),console.log(f.default.gray(`Use "sinch config --help" for available options
111
- `))}catch(n){console.error(f.default.red(`Failed to manage config: ${n.message}`)),process.exit(1)}});z.command("health").description("Check API connection and health").action(async()=>{let{SinchAPI:o}=(L(),O(De)),{config:e}=(I(),O(he)),{spinner:n}=(j(),O(Pe));try{await e.load();let i=new o(e.getApiConfig());n.start("Checking API health...");let r=await i.healthCheck();n.succeed("API is healthy"),console.log(f.default.blue(`
108
+ `))}catch(n){console.error(f.default.red(`Failed to manage config: ${n.message}`)),process.exit(1)}});z.command("health").description("Check API connection and health").action(async()=>{let{SinchAPI:o}=(_(),D($e)),{config:e}=(A(),D(fe)),{spinner:n}=(F(),D(ke));try{await e.load();let i=new o(e.getApiConfig());n.start("Checking API health...");let r=await i.checkHealth();n.succeed("API is healthy"),console.log(f.default.blue(`
112
109
  \u{1F3E5} Health Status:`)),console.log(` Status: ${f.default.green(r.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(f.default.red(`
113
- \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 o=>{let e=o.shell.toLowerCase();o.install&&e==="powershell"?await ui():e==="powershell"?fi():e==="bash"?gi():e==="zsh"?mi():(console.error(f.default.red(`Unsupported shell: ${e}`)),console.log("Supported shells: powershell, bash, zsh"),process.exit(1))});process.on("uncaughtException",o=>{console.error(f.default.red(`
110
+ \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 o=>{let e=o.shell.toLowerCase();o.install&&e==="powershell"?await ci():e==="powershell"?di():e==="bash"?pi():e==="zsh"?fi():(console.error(f.default.red(`Unsupported shell: ${e}`)),console.log("Supported shells: powershell, bash, zsh"),process.exit(1))});process.on("uncaughtException",o=>{console.error(f.default.red(`
114
111
  \u{1F4A5} Uncaught Exception: ${o.message}`)),process.env.DEBUG&&console.error(o.stack),process.exit(1)});process.on("unhandledRejection",o=>{console.error(f.default.red(`
115
- \u{1F4A5} Unhandled Rejection: ${o}`)),process.env.DEBUG&&console.error(o),process.exit(1)});async function li(){let o=process.argv.slice(2),e=o[0],n=["auth","help","completion","--help","-h","--version","-V"],i=o.includes("--non-interactive");if(e&&!n.includes(e)&&!n.some(r=>o.includes(r))){let{config:r}=(I(),O(he));if(await r.load(),!await r.hasCredentials()){i&&(console.error(f.default.red(`
112
+ \u{1F4A5} Unhandled Rejection: ${o}`)),process.env.DEBUG&&console.error(o),process.exit(1)});async function ai(){let o=process.argv.slice(2),e=o[0],n=["auth","help","completion","--help","-h","--version","-V"],i=o.includes("--non-interactive");if(e&&!n.includes(e)&&!n.some(r=>o.includes(r))){let{config:r}=(A(),D(fe));if(await r.load(),!await r.hasCredentials()){i&&(console.error(f.default.red(`
116
113
  \u274C Authentication required`)),console.error("Please set up authentication first with: sinch auth login"),console.error("Or provide credentials via environment variables for CI/CD"),process.exit(1));let s=require("inquirer");console.log(f.default.yellow(`
117
114
  \u26A0\uFE0F Authentication Required`)),console.log(`You need to authenticate with Sinch to use the CLI.
118
115
  `);let{shouldLogin:a}=await s.prompt([{type:"confirm",name:"shouldLogin",message:"Would you like to login now?",default:!0}]);a?process.argv.splice(2,process.argv.length-2,"auth","login"):(console.log(`
119
116
  You can authenticate anytime with:`),console.log(` ${f.default.cyan("sinch auth login")}
120
117
  `),process.exit(0))}}z.parse(process.argv),process.argv.slice(2).length||(console.log(f.default.blue.bold(`
121
118
  \u{1F3AF} Sinch Functions CLI`)),console.log(f.default.gray(`Serverless function platform for voice applications
122
- `)),console.log("Quick start:"),console.log(` ${f.default.cyan("sinch auth login")} # Authenticate with Sinch Voice API`),console.log(` ${f.default.cyan("sinch templates list")} # Browse available templates`),console.log(` ${f.default.cyan("sinch functions init")} # Create a new function`),console.log(` ${f.default.cyan("sinch functions dev")} # Start local development`),console.log(` ${f.default.cyan("sinch voice callback-url")} # Update webhook URL for live testing`),console.log(` ${f.default.cyan("sinch functions deploy")} # Deploy to production`),console.log(` ${f.default.cyan("sinch functions status [id]")} # Check deployment status`),console.log(` ${f.default.cyan("sinch secrets list")} # Manage custom secrets`),console.log(""),z.help())}li().catch(o=>{console.error(f.default.red("Error:"),o.message),process.exit(1)});async function ui(){let{spinner:o}=(j(),O(Pe));try{o.start("Installing PowerShell completion...");let e=ze.default.join(Ct.default.homedir(),"Documents","PowerShell"),n=ze.default.join(e,"sinch-completion.ps1");await de.default.ensureDir(e),o.update("Creating completion script...");let i=pi();await de.default.writeFile(n,i),o.update("Updating PowerShell profile...");let r=await di(),s="";await de.default.pathExists(r)&&(s=await de.default.readFile(r,"utf8"));let a='. "$env:USERPROFILE\\Documents\\PowerShell\\sinch-completion.ps1"';if(s.includes("sinch-completion.ps1"))o.info("PowerShell completion already installed"),console.log(f.default.blue(`
119
+ `)),console.log("Quick start:"),console.log(` ${f.default.cyan("sinch auth login")} # Authenticate with Sinch Voice API`),console.log(` ${f.default.cyan("sinch templates list")} # Browse available templates`),console.log(` ${f.default.cyan("sinch functions init")} # Create a new function`),console.log(` ${f.default.cyan("sinch functions dev")} # Start local development`),console.log(` ${f.default.cyan("sinch voice callback-url")} # Update webhook URL for live testing`),console.log(` ${f.default.cyan("sinch functions deploy")} # Deploy to production`),console.log(` ${f.default.cyan("sinch functions status [id]")} # Check deployment status`),console.log(` ${f.default.cyan("sinch secrets list")} # Manage custom secrets`),console.log(""),z.help())}ai().catch(o=>{console.error(f.default.red("Error:"),o.message),process.exit(1)});async function ci(){let{spinner:o}=(F(),D(ke));try{o.start("Installing PowerShell completion...");let e=He.default.join(Ct.default.homedir(),"Documents","PowerShell"),n=He.default.join(e,"sinch-completion.ps1");await le.default.ensureDir(e),o.update("Creating completion script...");let i=ui();await le.default.writeFile(n,i),o.update("Updating PowerShell profile...");let r=await li(),s="";await le.default.pathExists(r)&&(s=await le.default.readFile(r,"utf8"));let a='. "$env:USERPROFILE\\Documents\\PowerShell\\sinch-completion.ps1"';if(s.includes("sinch-completion.ps1"))o.info("PowerShell completion already installed"),console.log(f.default.blue(`
123
120
  \u2139\uFE0F Completion is already installed`)),console.log(f.default.gray("If tab completion isn't working, try restarting PowerShell"));else{let c=s+(s?`
124
121
  `:"")+`# Sinch Functions CLI completion
125
122
  `+a+`
126
- `;await de.default.writeFile(r,c),o.succeed("PowerShell completion installed successfully!"),console.log(f.default.green(`
123
+ `;await le.default.writeFile(r,c),o.succeed("PowerShell completion installed successfully!"),console.log(f.default.green(`
127
124
  \u2705 Installation Complete!`)),console.log(f.default.blue("\u{1F4C1} Files created:")),console.log(` ${f.default.gray(n)}`),console.log(` ${f.default.gray("Updated:")} ${r}`),console.log(f.default.yellow(`
128
125
  \u26A1 To activate completion:`)),console.log(" 1. Restart PowerShell, OR"),console.log(" 2. Run: "+f.default.cyan(". $PROFILE")),console.log(f.default.gray(`
129
126
  \u{1F4A1} Test with: sinch functions <TAB>`))}}catch(e){o.fail("Failed to install PowerShell completion"),console.error(f.default.red(`\u274C Error: ${e.message}`)),console.log(f.default.yellow(`
130
- \u{1F4A1} Try manual installation with: sinch completion`)),process.exit(1)}}async function di(){return new Promise(o=>{let e=n=>new Promise(i=>{let r=(0,Wn.spawn)(n,["-Command","$PROFILE"],{stdio:["ignore","pipe","pipe"]}),s="";r.stdout.on("data",a=>{s+=a.toString()}),r.on("close",a=>{i(a===0?{success:!0,path:s.trim(),version:n}:{success:!1})}),r.on("error",()=>{i({success:!1})})});e("pwsh").then(n=>{n.success&&n.path?(console.log(f.default.gray(` Detected PowerShell 7 profile: ${n.path}`)),o(n.path)):e("powershell").then(i=>{if(i.success&&i.path)console.log(f.default.gray(` Detected Windows PowerShell profile: ${i.path}`)),o(i.path);else{let r=ze.default.join(Ct.default.homedir(),"Documents","PowerShell","Microsoft.PowerShell_profile.ps1");console.log(f.default.gray(` Using fallback profile path: ${r}`)),o(r)}})})})}function pi(){return`# PowerShell completion for Sinch Functions CLI
127
+ \u{1F4A1} Try manual installation with: sinch completion`)),process.exit(1)}}async function li(){return new Promise(o=>{let e=n=>new Promise(i=>{let r=(0,Jn.spawn)(n,["-Command","$PROFILE"],{stdio:["ignore","pipe","pipe"]}),s="";r.stdout.on("data",a=>{s+=a.toString()}),r.on("close",a=>{i(a===0?{success:!0,path:s.trim(),version:n}:{success:!1})}),r.on("error",()=>{i({success:!1})})});e("pwsh").then(n=>{n.success&&n.path?(console.log(f.default.gray(` Detected PowerShell 7 profile: ${n.path}`)),o(n.path)):e("powershell").then(i=>{if(i.success&&i.path)console.log(f.default.gray(` Detected Windows PowerShell profile: ${i.path}`)),o(i.path);else{let r=He.default.join(Ct.default.homedir(),"Documents","PowerShell","Microsoft.PowerShell_profile.ps1");console.log(f.default.gray(` Using fallback profile path: ${r}`)),o(r)}})})})}function ui(){return`# PowerShell completion for Sinch Functions CLI
131
128
  # Auto-generated by 'sinch completion --install'
132
129
  # Compatible with both PowerShell 7 and Windows PowerShell 5.1
133
130
 
@@ -174,7 +171,7 @@ Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
174
171
  # Silently fail if there are any errors in completion
175
172
  # This prevents PowerShell startup errors
176
173
  }
177
- }`}function fi(){let o=`
174
+ }`}function di(){let o=`
178
175
  # PowerShell completion for Sinch Functions CLI
179
176
  Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
180
177
  param($wordToComplete, $commandAst, $cursorPosition)
@@ -225,7 +222,7 @@ Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
225
222
  #
226
223
  # To find your profile location, run: $PROFILE
227
224
  `;console.log(f.default.blue("\u{1F527} PowerShell Completion Script")),console.log(f.default.gray(`Copy and save this to your PowerShell profile:
228
- `)),console.log(o),console.log(f.default.yellow("Installation Instructions:")),console.log(f.default.green("\u{1F680} Easy way: ")+f.default.cyan("sinch completion --install")),console.log(f.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(f.default.cyan(' . "$env:USERPROFILE\\\\Documents\\\\PowerShell\\\\sinch-completion.ps1"')),console.log("3. Restart PowerShell or run: . $PROFILE")}function gi(){let o=`
225
+ `)),console.log(o),console.log(f.default.yellow("Installation Instructions:")),console.log(f.default.green("\u{1F680} Easy way: ")+f.default.cyan("sinch completion --install")),console.log(f.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(f.default.cyan(' . "$env:USERPROFILE\\\\Documents\\\\PowerShell\\\\sinch-completion.ps1"')),console.log("3. Restart PowerShell or run: . $PROFILE")}function pi(){let o=`
229
226
  # Bash completion for Sinch Functions CLI
230
227
  _sinch_completion() {
231
228
  local cur prev commands
@@ -266,7 +263,7 @@ complete -F _sinch_completion sinch
266
263
 
267
264
  # To install: Add this to your ~/.bashrc or ~/.bash_profile
268
265
  `;console.log(f.default.blue("\u{1F527} Bash Completion Script")),console.log(f.default.gray(`Add this to your ~/.bashrc or ~/.bash_profile:
269
- `)),console.log(o)}function mi(){let o=`
266
+ `)),console.log(o)}function fi(){let o=`
270
267
  #compdef sinch
271
268
 
272
269
  _sinch() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinch/cli",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Official Sinch CLI - Manage all Sinch products from your terminal",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -13,6 +13,8 @@
13
13
  "build:prod": "tsup src/index.ts --format cjs --dts --clean --minify",
14
14
  "typecheck": "tsc --noEmit",
15
15
  "test": "jest",
16
+ "test:e2e": "jest --config tests/e2e/jest.config.js",
17
+ "test:e2e:staging": "jest --config tests/e2e/jest.config.js --env=staging",
16
18
  "prepublishOnly": "npm run build:prod"
17
19
  },
18
20
  "keywords": [],
@@ -55,6 +57,7 @@
55
57
  "@types/inquirer": "^9.0.9",
56
58
  "@types/keytar": "^4.4.0",
57
59
  "@types/node": "^24.3.0",
60
+ "execa": "^5.1.1",
58
61
  "jest": "^29.7.0",
59
62
  "nodemon": "^3.0.1",
60
63
  "tsup": "^8.5.0",