@sinch/cli 0.1.25-beta.0 → 0.1.27-beta.0

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 +108 -96
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,22 +1,22 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var ro=Object.create;var We=Object.defineProperty;var ao=Object.getOwnPropertyDescriptor;var co=Object.getOwnPropertyNames;var lo=Object.getPrototypeOf,uo=Object.prototype.hasOwnProperty;var le=(i,e)=>()=>(i&&(e=i(i=0)),e);var K=(i,e)=>()=>(e||i((e={exports:{}}).exports,e),e.exports),He=(i,e)=>{for(var n in e)We(i,n,{get:e[n],enumerable:!0})},Ft=(i,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of co(e))!uo.call(i,s)&&s!==n&&We(i,s,{get:()=>e[s],enumerable:!(o=ao(e,s))||o.enumerable});return i};var h=(i,e,n)=>(n=i!=null?ro(lo(i)):{},Ft(e||!i||!i.__esModule?We(n,"default",{value:i,enumerable:!0}):n,i)),_=i=>Ft(We({},"__esModule",{value:!0}),i);var nt=K((Oi,po)=>{po.exports={name:"@sinch/cli",version:"0.1.25-beta.0",description:"Official Sinch CLI - Manage all Sinch products from your terminal",main:"dist/index.js",bin:{sinch:"bin/sinch"},scripts:{start:"tsx src/index.ts",dev:"tsx watch src/index.ts",build:"tsc && node scripts/post-build.js","build:prod":"tsup src/index.ts --format cjs --dts --clean --minify",typecheck:"tsc --noEmit",test:"jest","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.7",keytar:"^7.9.0",ora:"^4.1.1"},devDependencies:{"@types/adm-zip":"^0.5.7","@types/blessed":"^0.1.25","@types/fs-extra":"^11.0.4","@types/inquirer":"^9.0.9","@types/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 Ae={};He(Ae,{SinchAPI:()=>A});var Ge,st,Ie,A,U=le(()=>{"use strict";Ge=h(require("axios")),st=h(require("form-data")),Ie=h(require("chalk")),A=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=Ge.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 o=await this.getValidToken();o&&(n.headers.Authorization=`${o.token_type} ${o.access_token}`)}return process.env.DEBUG_HTTP&&console.log(Ie.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(Ie.default.gray(`\u2190 ${n.status} ${n.config.url}`)),n),async n=>{if(process.env.DEBUG_HTTP&&console.log(Ie.default.red(`\u2190 ${n.response?.status||"ERROR"} ${n.config?.url}`)),n.response?.status===401&&this.credentials&&n.config){let o=n.config;if(!o._retry){o._retry=!0;try{let s=await this.getValidToken();if(s)return o.headers.Authorization=`${s.token_type} ${s.access_token}`,this.client.request(o)}catch{console.error(Ie.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 o=n?{category:n}:{};return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}`,{params:o})).data}catch(o){throw this._handleError(o,`Failed to list ${e} templates`)}}async getTemplateDetails(e,n){try{return(await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}`)).data}catch(o){throw this._handleError(o,`Failed to get template details for ${e}/${n}`)}}async downloadTemplate(e,n){try{let o=await this.client.get(`/v1/projects/${this.projectId}/templates/${e}/${n}/download`,{responseType:"arraybuffer"});return Buffer.from(o.data)}catch(o){throw this._handleError(o,`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,o,s,r="public"){try{let a=new st.default;return a.append("name",e),a.append("runtime",n),a.append("code",o,{filename:"function.zip"}),a.append("accessLevel",r),s&&a.append("configuration",JSON.stringify(s)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,a,{headers:{...a.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(a){throw this._handleError(a,"Failed to deploy function")}}async updateFunction(e,n,o){try{let s=new st.default;return s.append("code",n,{filename:"function.zip"}),o&&s.append("configuration",JSON.stringify(o)),(await this.client.put(`/v1/projects/${this.projectId}/functions/${e}`,s,{headers:{...s.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(s){throw this._handleError(s,`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(o){throw this._handleError(o,`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",o="function"){try{return(await this.client.post(`/v1/projects/${this.projectId}/test/documentation`,{Code:e,Runtime:n,Name:o})).data}catch(s){throw this._handleError(s,"Failed to generate documentation from code")}}async generateDocumentationForFunction(e,n){try{let o=n?{MarkdownOverride:n}:{};return(await this.client.post(`/v1/projects/${this.projectId}/functions/${e}/documentation`,o)).data}catch(o){throw this._handleError(o,`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,o){let s=c=>c.status?"status":c.progress?"progress":c.completed?"completed":c.failed||c.error?"failed":c.connected?"connected":"message",r=new URL(`v1/projects/${this.projectId}/functions/${e}/deployment/stream`,this.baseUrl).href,a={Accept:"text/event-stream","Cache-Control":"no-cache"};if(this.credentials)try{let c=await this.credentials.retrieve();if(c&&c.keyId&&c.keySecret){let l=Buffer.from(`${c.keyId}:${c.keySecret}`).toString("base64");a.Authorization=`Basic ${l}`}}catch(c){console.error("Failed to add authentication:",c)}let u=null;try{u=new AbortController;let c=await fetch(r,{method:"GET",headers:a,signal:u.signal});if(!c.ok)throw new Error(`SSE connection failed: ${c.status} ${c.statusText}`);if(!c.body)throw new Error("Response body is null");let l=c.body.getReader(),p=new TextDecoder,m="";return(async()=>{let w="";try{for(;;){let{done:v,value:O}=await l.read();if(v)break;let H=p.decode(O,{stream:!0});m+=H;let E=m.split(`
3
- `);m=E.pop()||"";for(let b of E){if(b.startsWith("event:")){w=b.substring(6).trim();continue}if(b.startsWith("data:")){let S=b.substring(5).trim();if(S)try{let y=JSON.parse(S),$=w||s(y);n({type:$,data:y}),w=""}catch{n({type:w||"message",data:S}),w=""}}b===""&&(w="")}}}catch(v){v.name!=="AbortError"&&o&&o(v)}})(),()=>{u&&u.abort()}}catch(c){throw console.error("Failed to create SSE stream:",c),o&&o(c),c}}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(Ie.default.yellow("Failed to get authentication token:",e.message)),null}}async authenticateOAuth(e,n){try{let o=this.oauthUrl,s=new URLSearchParams;s.append("grant_type","client_credentials");let a=(await Ge.default.post(o,s,{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(o){throw this._handleError(o,"OAuth authentication failed")}}_handleError(e,n){if(Ge.default.isAxiosError(e)){let o=e;if(o.response){let s=o.response.status,r=o.response.data,a=r?.message||r?.error||o.message;throw s===401?new Error('Authentication required. Please run "sinch auth login" first.'):s===403?new Error(`Permission denied: ${a}`):s===404?new Error(`Resource not found: ${a}`):s>=500?new Error(`Server error: ${a}`):new Error(`${n}: ${a}`)}else throw o.request?(console.error("DEBUG: Axios error details:",{code:o.code,message:o.message,url:o.config?.url,baseURL:o.config?.baseURL,method:o.config?.method}),o.code==="ECONNREFUSED"?new Error(`Cannot connect to API at ${this.baseUrl}. Is the server running?`):o.code==="ETIMEDOUT"?new Error(`Request timeout after ${this.timeout}ms`):new Error(`${n}: No response from server (${o.code||"unknown error"})`)):new Error(`${n}: ${o.message}`)}else throw new Error(`${n}: ${e.message||e}`)}}});function Ye(){if(!rt)try{rt=require("keytar")}catch{return null}return rt}var Lt,ne,rt,Fe,V,ze,xt=le(()=>{"use strict";Lt=h(require("os")),ne=h(require("chalk")),rt=null;Fe="sinch-functions-cli",V=Lt.userInfo().username,ze=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=Ye();if(!e)return this.keychainAvailable=!1,!1;let n=`${V}-test-${Date.now()}`;return await e.setPassword(Fe,n,"test"),await e.deletePassword(Fe,n),this.keychainAvailable=!0,!0}catch{return this.keychainAvailable=!1,!1}}async setPassword(e,n){if(!await this.isKeychainAvailable())return!1;let s=Ye();return s?(await s.setPassword(Fe,e,n),!0):!1}async getPassword(e){if(!await this.isKeychainAvailable())return null;let o=Ye();return o?await o.getPassword(Fe,e):null}async deletePassword(e){if(!await this.isKeychainAvailable())return!1;try{let o=Ye();return o?(await o.deletePassword(Fe,e),!0):!1}catch{return!0}}async store(e){let{projectId:n,keyId:o,keySecret:s,applicationKey:r,applicationSecret:a}=e,u=await this.setPassword(`${V}-keySecret`,s),c=await this.setPassword(r,a);u&&c?(this.config.set("keySecretPlaintext",null),this.config.set("applicationSecretPlaintext",null)):(console.log(ne.default.yellow(`
4
- \u26A0\uFE0F OS keychain not available (Docker/CI environment detected)`)),console.log(ne.default.yellow("\u26A0\uFE0F Storing secrets in plaintext config file")),console.log(ne.default.gray("Location: ~/.sinch/config.json")),console.log(ne.default.gray(`
5
- For better security, export as environment variables instead:`)),console.log(ne.default.cyan(' export SINCH_KEY_SECRET="'+s+'"')),console.log(ne.default.cyan(' export SINCH_APPLICATION_SECRET="'+a+'"')),this.config.set("keySecretPlaintext",s),this.config.set("applicationSecretPlaintext",a)),this.config.set("projectId",n),this.config.set("keyId",o),this.config.set("defaultApplicationKey",r),this.config.set("credentialsStored",!0),await this.config.save()}async storeOAuthToken(e){let{access_token:n,refresh_token:o,expires_in:s,token_type:r}=e,a=new Date(Date.now()+s*1e3).toISOString(),u=await this.setPassword(`${V}-oauth-access`,n),c=!0;o&&(c=await this.setPassword(`${V}-oauth-refresh`,o)),this.config.set("oauthTokenType",r),this.config.set("oauthExpiresAt",a),this.config.set("oauthStored",u&&c),await this.config.save()}async reAuthenticateOAuth(){try{let e=await this.retrieve();if(!e)return null;let{SinchAPI:n}=(U(),_(Ae)),s=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(s),s.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(ne.default.gray("Token expired, re-authenticating..."));let o=await this.reAuthenticateOAuth();return o?console.log(ne.default.green("\u2713 Token renewed successfully")):console.warn(ne.default.yellow("Failed to renew OAuth token. Please login again.")),o}return await this.getPassword(`${V}-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,o=process.env.SINCH_APPLICATION_KEY,s=process.env.SINCH_APPLICATION_SECRET;if(e&&n&&o&&s)return{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId")||"",keyId:e,keySecret:n,applicationKey:o,applicationSecret:s};if(!this.config.get("credentialsStored"))return null;let a=this.config.get("projectId"),u=this.config.get("keyId"),c=this.config.get("defaultApplicationKey"),l=await this.getPassword(`${V}-keySecret`),p=c?await this.getPassword(c):null;return(!l||!p)&&(l=l||n||null,p=p||s||null),(!l||!p)&&(l=l||this.config.get("keySecretPlaintext"),p=p||this.config.get("applicationSecretPlaintext")),!l||!p?null:{projectId:a,keyId:u,keySecret:l,applicationKey:c,applicationSecret:p}}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(`${V}-keySecret`),await this.deletePassword(`${V}-oauth-access`),await this.deletePassword(`${V}-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 o=await this.getPassword(`${V}-keySecret`),s=this.config.get("defaultApplicationKey"),r=s?await this.getPassword(s):null;return!!(o&&r)}async hasOAuthToken(){return this.config.get("oauthStored")?!!await this.getPassword(`${V}-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:o}=require("@sinch/sdk-core");return new o({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret,projectId:this.config.get("projectId")})}async storeBasicAuthToken(e){await this.setPassword(`${V}-basic-auth`,e)&&(this.config.set("basicAuthStored",!0),await this.config.save())}async getBasicAuthToken(){return this.config.get("basicAuthStored")?await this.getPassword(`${V}-basic-auth`):null}async clearBasicAuthToken(){await this.deletePassword(`${V}-basic-auth`),this.config.set("basicAuthStored",!1),await this.config.save()}}});var Ce={};He(Ce,{Config:()=>Qe,config:()=>f});var G,_e,Nt,at,Qe,f,j=le(()=>{"use strict";G=h(require("fs-extra")),_e=h(require("path")),Nt=h(require("os")),at=h(require("chalk"));xt();Qe=class{configDir;configFile;projectConfigFile;_config=null;_projectConfig=null;_credentials=null;constructor(){this.configDir=_e.join(Nt.homedir(),".sinch"),this.configFile=_e.join(this.configDir,"config.json"),this.projectConfigFile=_e.join(process.cwd(),"sinch.json")}async load(){try{await G.ensureDir(this.configDir),await G.pathExists(this.configFile)?this._config=await G.readJson(this.configFile):(this._config=this._getDefaultConfig(),await this.save())}catch(e){console.warn(at.default.yellow(`Warning: Could not load config: ${e.message}`)),this._config=this._getDefaultConfig()}this._credentials=new ze(this);try{await G.pathExists(this.projectConfigFile)&&(this._projectConfig=await G.readJson(this.projectConfigFile))}catch(e){console.warn(at.default.yellow(`Warning: Could not load project config: ${e.message}`))}}async save(){try{await G.ensureDir(this.configDir),await G.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=_e.join(process.cwd(),"sinch.json");await G.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,o=!1){if(!this._config)throw new Error("Config not loaded. Call load() first.");o?(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",o={},s=null){let r={name:e,runtime:n,description:`Sinch Functions project: ${e}`,created:new Date().toISOString()};return o&&Object.keys(o).length>0&&(r.variables=o),s&&(r.applicationKey=s),this._projectConfig=r,await this.saveProjectConfig(),r}isInProject(){return this._projectConfig!==null}getProjectConfig(){return this._projectConfig}_getDefaultConfig(){return{apiUrl:"https://functions.api.sinch.com",oauthUrl:"https://auth.sinch.com/oauth2/token",projectId:"default-project",created:new Date().toISOString()}}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()}},f=new Qe});var Y,ue,ct,Ut,lt,t,B=le(()=>{"use strict";Y=h(require("chalk")),ue=h(require("fs")),ct=h(require("path")),Ut=h(require("os")),lt=class{verbose;logFile;constructor(e={}){this.verbose=e.verbose||process.env.VERBOSE==="true";let n="cli";try{let o=ct.join(process.cwd(),"sinch.json");ue.existsSync(o)&&(n=JSON.parse(ue.readFileSync(o,"utf8")).name||"cli")}catch{}this.logFile=ct.join(Ut.tmpdir(),`sinch-${n}.log`);try{ue.writeFileSync(this.logFile,`=== Sinch CLI Debug Log - ${new Date().toISOString()} ===
6
- `,{flag:"w"})}catch{}}writeToFile(e,n,...o){try{let r=`[${new Date().toISOString()}] ${e}: ${n} ${o.length>0?JSON.stringify(o):""}
7
- `;ue.appendFileSync(this.logFile,r)}catch{}}info(e,...n){console.log(Y.default.blue("\u2139"),e,...n),this.writeToFile("INFO",e,...n)}success(e,...n){console.log(Y.default.green("\u2705"),e,...n),this.writeToFile("SUCCESS",e,...n)}warn(e,...n){console.log(Y.default.yellow("\u26A0\uFE0F "),e,...n),this.writeToFile("WARN",e,...n)}error(e,...n){console.log(Y.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(Y.default.gray("\u{1F41B}"),Y.default.gray(e),...n)}log(e,...n){console.log(e,...n)}title(e){console.log(Y.default.blue.bold(`
8
- \u{1F3AF} ${e}`))}subtitle(e){console.log(Y.default.gray(`
9
- ${e}`))}list(e,n={}){let{indent:o=" ",bullet:s="\u2022"}=n;e.forEach(r=>{console.log(`${o}${Y.default.gray(s)} ${r}`)})}calculateColumnWidths(e,n){let o=e.map(s=>s.length);return n.forEach(s=>{s.forEach((r,a)=>{o[a]=Math.max(o[a]??0,String(r).length)})}),o}table(e,n){let o=this.calculateColumnWidths(e,n),s=e.map((r,a)=>r.padEnd(o[a]??0)).join(" ");console.log(Y.default.bold(s)),console.log(Y.default.gray("-".repeat(s.length))),n.forEach(r=>{let a=r.map((u,c)=>String(u).padEnd(o[c]??0)).join(" ");console.log(a)})}newline(){console.log()}},t=new lt});var Re={};He(Re,{Spinner:()=>Ze,spinner:()=>d});var Bt,Kt,Ze,d,L=le(()=>{"use strict";Bt=h(require("ora")),Kt=h(require("cli-spinners")),Ze=class{spinner=null;spinnerType=Kt.default.dots;start(e){return this.spinner=(0,Bt.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 Ze});var Wt=K((Mi,Mt)=>{"use strict";var F=h(require("fs-extra")),de=h(require("path")),q=h(require("chalk")),be=h(require("inquirer")),Vt=require("commander");j();B();L();U();var je=require("child_process"),qt=h(require("adm-zip")),ut=h(require("keytar")),Jt=new Vt.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(i,e)=>{try{await f.load();let n=process.cwd(),o=new A(f.getApiConfig()),s=e.runtime;s||(e.nonInteractive?s="node":s=(await be.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 ${s}...`);let r=await o.listRuntimeTemplates(s);if(d.stop(),!r.templates||r.templates.length===0)throw new Error(`No templates available for runtime '${s}'`);let a=i;if(!a)if(e.nonInteractive){let b=r.templates.filter(S=>S.name&&S.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=r.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 be.default.prompt([{type:"list",name:"selectedTemplate",message:"Choose a template:",choices:b,pageSize:10}])).selectedTemplate}let u=e.name;u||(e.nonInteractive?u=a:u=(await be.default.prompt([{type:"input",name:"name",message:"Function name:",default:a,validate:S=>!S||S.trim().length===0?"Function name is required":/^[a-z][a-z0-9-]*$/.test(S.trim())?!0:"Function name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens"}])).name.trim());let c=de.default.join(n,u);if(await F.default.pathExists(c)){let b=!1;if(e.nonInteractive?(b=!0,t.info(`Directory '${u}' already exists. Overwriting (non-interactive mode)...`)):b=(await be.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${u}' already exists. Overwrite?`,default:!1}])).overwrite,!b){t.info("Initialization cancelled");return}await F.default.remove(c)}await F.default.ensureDir(c);let l=r.templates.find(b=>b.name===a);if(!l){let b=r.templates.map(S=>S.name).join(", ");throw new Error(`Template '${a}' not found. Available templates: ${b}`)}let p=["node","csharp"];if(!p.includes(s))throw new Error(`Runtime '${s}' not supported. Supported runtimes: ${p.join(", ")}`);d.start(`\u{1F680} Initializing ${u} with ${a} template (${s})...`);let m=await o.downloadTemplate(s,a);new qt.default(m).extractAllTo(c,!0),d.succeed("\u{1F4E6} Template extracted");let w={},v=[],O=de.default.join(c,"template.json");if(await F.default.pathExists(O)){let b=await F.default.readJson(O);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[y,$]of Object.entries(b.variables)){let R;typeof $=="string"?R=$:R=$.default||"",w[y]=R,t.info(` ${y}: ${R}`)}}else{t.newline(),t.info("\u{1F4DD} Configure template variables:");for(let[y,$]of Object.entries(b.variables)){let R;typeof $=="string"?R={type:"input",name:y,message:`${y.replace(/_/g," ").toLowerCase()}:`,default:$}:(R={type:$.type==="number"?"number":"input",name:y,message:`${$.description||y.replace(/_/g," ").toLowerCase()}:`,default:$.default},$.type==="number"&&(R.validate=ce=>$.min!==void 0&&ce<$.min?`Value must be at least ${$.min}`:$.max!==void 0&&ce>$.max?`Value must be at most ${$.max}`:!0));let he=await be.default.prompt([R]);w[y]=he[y]}}let S="sinch-functions-cli";if(b.secrets&&Object.keys(b.secrets).length>0)if(v=Object.keys(b.secrets),e.nonInteractive){t.info("\u{1F4DD} Template secrets detected (non-interactive mode):");for(let y of Object.keys(b.secrets))t.info(` ${y}: [will need to be set manually]`)}else{t.newline(),t.info("\u{1F510} Configure template secrets (stored securely in OS keychain):");for(let[y,$]of Object.entries(b.secrets)){let R=$.description||y.replace(/_/g," ").toLowerCase(),he=$.required!==!1,ce={type:"password",name:y,message:`${R}:`,validate:N=>he&&(!N||N.trim()==="")?"This secret is required":!0},Oe=(await be.default.prompt([ce]))[y];if(Oe&&Oe.trim()!=="")try{let N=`${u}-${y}`;await ut.default.setPassword(S,N,Oe),t.info(` \u2705 ${y} stored securely in keychain`)}catch(N){t.warn(` \u26A0\uFE0F Could not store ${y} in keychain: ${N.message}`),t.info(` \u{1F4A1} You can add it later with: sinch secrets add ${y} <value>`)}}}await F.default.remove(O)}d.start("\u{1F527} Finalizing function configuration...");let H=de.default.join(c,"sinch.json"),E;if(await F.default.pathExists(H)){if(E=await F.default.readJson(H),E.name=u,E.description=`Sinch Functions function: ${u}`,E.functionId=null,delete E.projectId,delete E.voiceAppId,E.variables)for(let[b,S]of Object.entries(E.variables))typeof S=="string"&&(S==="your-project-id"||S==="{{PROJECT_ID}}"?E.variables[b]=f.get("projectId"):(S==="your-application-key"||S==="{{SINCH_APPLICATION_KEY}}")&&(E.variables[b]=f.get("defaultApplicationKey")));E.created=new Date().toISOString(),E.variables={},E.secrets&&delete E.secrets}else E={name:u,functionId:null,runtime:s,description:`Sinch Functions function: ${u}`,created:new Date().toISOString(),variables:{},custom:{}};if(await F.default.writeJson(H,E,{spaces:2}),s==="node"){let b=de.default.join(c,"package.json");if(await F.default.pathExists(b)){let P=await F.default.readJson(b);P.name=u,P.description=E.description,await F.default.writeJson(b,P,{spaces:2})}let S=de.default.join(c,".env"),y=`# Sinch Functions Environment Variables
2
+ "use strict";var ti=Object.create;var st=Object.defineProperty;var ni=Object.getOwnPropertyDescriptor;var oi=Object.getOwnPropertyNames;var ii=Object.getPrototypeOf,si=Object.prototype.hasOwnProperty;var re=(o,e)=>()=>(o&&(e=o(o=0)),e);var F=(o,e)=>()=>(e||o((e={exports:{}}).exports,e),e.exports),Ke=(o,e)=>{for(var n in e)st(o,n,{get:e[n],enumerable:!0})},Zt=(o,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of oi(e))!si.call(o,s)&&s!==n&&st(o,s,{get:()=>e[s],enumerable:!(i=ni(e,s))||i.enumerable});return o};var m=(o,e,n)=>(n=o!=null?ti(ii(o)):{},Zt(e||!o||!o.__esModule?st(n,"default",{value:o,enumerable:!0}):n,o)),M=o=>Zt(st({},"__esModule",{value:!0}),o);var mt=F((xs,ri)=>{ri.exports={name:"@sinch/cli",version:"0.1.27-beta.0",description:"Official Sinch CLI - Manage all Sinch products from your terminal",main:"dist/index.js",bin:{sinch:"bin/sinch"},scripts:{start:"tsx src/index.ts",dev:"tsx watch src/index.ts",build:"tsc && node scripts/post-build.js","build:prod":"tsup src/index.ts --format cjs --dts --clean --minify",typecheck:"tsc --noEmit",test:"jest","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.7",keytar:"^7.9.0",ora:"^4.1.1"},devDependencies:{"@types/adm-zip":"^0.5.7","@types/blessed":"^0.1.25","@types/fs-extra":"^11.0.4","@types/inquirer":"^9.0.9","@types/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 Fe={};Ke(Fe,{SinchAPI:()=>j});var rt,wt,Ne,j,K=re(()=>{"use strict";rt=m(require("axios")),wt=m(require("form-data")),Ne=m(require("chalk")),j=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=rt.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(Ne.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(Ne.default.gray(`\u2190 ${n.status} ${n.config.url}`)),n),async n=>{if(process.env.DEBUG_HTTP&&console.log(Ne.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 s=await this.getValidToken();if(s)return i.headers.Authorization=`${s.token_type} ${s.access_token}`,this.client.request(i)}catch{console.error(Ne.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,s,a="public"){try{let r=new wt.default;return r.append("name",e),r.append("runtime",n),r.append("code",i,{filename:"function.zip"}),r.append("accessLevel",a),s&&r.append("configuration",JSON.stringify(s)),(await this.client.post(`/v1/projects/${this.projectId}/functions`,r,{headers:{...r.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(r){throw this._handleError(r,"Failed to deploy function")}}async updateFunction(e,n,i){try{let s=new wt.default;return s.append("code",n,{filename:"function.zip"}),i&&s.append("configuration",JSON.stringify(i)),(await this.client.put(`/v1/projects/${this.projectId}/functions/${e}`,s,{headers:{...s.getHeaders()},maxContentLength:1/0,maxBodyLength:1/0})).data}catch(s){throw this._handleError(s,`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(s){throw this._handleError(s,"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 s=d=>d.status?"status":d.progress?"progress":d.completed?"completed":d.failed||d.error?"failed":d.connected?"connected":"message",a=new URL(`v1/projects/${this.projectId}/functions/${e}/deployment/stream`,this.baseUrl).href,r={Accept:"text/event-stream","Cache-Control":"no-cache"};if(this.credentials)try{let d=await this.credentials.retrieve();if(d&&d.keyId&&d.keySecret){let p=Buffer.from(`${d.keyId}:${d.keySecret}`).toString("base64");r.Authorization=`Basic ${p}`}}catch(d){console.error("Failed to add authentication:",d)}let c=null;try{c=new AbortController;let d=await fetch(a,{method:"GET",headers:r,signal:c.signal});if(!d.ok)throw new Error(`SSE connection failed: ${d.status} ${d.statusText}`);if(!d.body)throw new Error("Response body is null");let p=d.body.getReader(),u=new TextDecoder,h="";return(async()=>{let w="";try{for(;;){let{done:v,value:U}=await p.read();if(v)break;let Z=u.decode(U,{stream:!0});h+=Z;let I=h.split(`
3
+ `);h=I.pop()||"";for(let b of I){if(b.startsWith("event:")){w=b.substring(6).trim();continue}if(b.startsWith("data:")){let S=b.substring(5).trim();if(S)try{let y=JSON.parse(S),$=w||s(y);n({type:$,data:y}),w=""}catch{n({type:w||"message",data:S}),w=""}}b===""&&(w="")}}}catch(v){v.name!=="AbortError"&&i&&i(v)}})(),()=>{c&&c.abort()}}catch(d){throw console.error("Failed to create SSE stream:",d),i&&i(d),d}}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(Ne.default.yellow("Failed to get authentication token:",e.message)),null}}async authenticateOAuth(e,n){try{let i=this.oauthUrl,s=new URLSearchParams;s.append("grant_type","client_credentials");let r=(await rt.default.post(i,s,{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(r),r}catch(i){throw this._handleError(i,"OAuth authentication failed")}}_handleError(e,n){if(rt.default.isAxiosError(e)){let i=e;if(i.response){let s=i.response.status,a=i.response.data,r=a?.message||a?.error||i.message;throw s===401?new Error('Authentication required. Please run "sinch auth login" first.'):s===403?new Error(`Permission denied: ${r}`):s===404?new Error(`Resource not found: ${r}`):s>=500?new Error(`Server error: ${r}`):new Error(`${n}: ${r}`)}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 at(){if(!Ct)try{Ct=require("keytar")}catch{return null}return Ct}var en,ae,Ct,Ve,W,ct,tn=re(()=>{"use strict";en=m(require("os")),ae=m(require("chalk")),Ct=null;Ve="sinch-functions-cli",W=en.userInfo().username,ct=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=at();if(!e)return this.keychainAvailable=!1,!1;let n=`${W}-test-${Date.now()}`;return await e.setPassword(Ve,n,"test"),await e.deletePassword(Ve,n),this.keychainAvailable=!0,!0}catch{return this.keychainAvailable=!1,!1}}async setPassword(e,n){if(!await this.isKeychainAvailable())return!1;let s=at();return s?(await s.setPassword(Ve,e,n),!0):!1}async getPassword(e){if(!await this.isKeychainAvailable())return null;let i=at();return i?await i.getPassword(Ve,e):null}async deletePassword(e){if(!await this.isKeychainAvailable())return!1;try{let i=at();return i?(await i.deletePassword(Ve,e),!0):!1}catch{return!0}}async store(e){let{projectId:n,keyId:i,keySecret:s,applicationKey:a,applicationSecret:r}=e,c=await this.setPassword(`${W}-keySecret`,s),d=await this.setPassword(a,r);c&&d?(this.config.set("keySecretPlaintext",null),this.config.set("applicationSecretPlaintext",null)):(console.log(ae.default.yellow(`
4
+ \u26A0\uFE0F OS keychain not available (Docker/CI environment detected)`)),console.log(ae.default.yellow("\u26A0\uFE0F Storing secrets in plaintext config file")),console.log(ae.default.gray("Location: ~/.sinch/config.json")),console.log(ae.default.gray(`
5
+ For better security, export as environment variables instead:`)),console.log(ae.default.cyan(' export SINCH_KEY_SECRET="'+s+'"')),console.log(ae.default.cyan(' export SINCH_APPLICATION_SECRET="'+r+'"')),this.config.set("keySecretPlaintext",s),this.config.set("applicationSecretPlaintext",r)),this.config.set("projectId",n),this.config.set("keyId",i),this.config.set("defaultApplicationKey",a),this.config.set("credentialsStored",!0),await this.config.save()}async storeOAuthToken(e){let{access_token:n,refresh_token:i,expires_in:s,token_type:a}=e,r=new Date(Date.now()+s*1e3).toISOString(),c=await this.setPassword(`${W}-oauth-access`,n),d=!0;i&&(d=await this.setPassword(`${W}-oauth-refresh`,i)),this.config.set("oauthTokenType",a),this.config.set("oauthExpiresAt",r),this.config.set("oauthStored",c&&d),await this.config.save()}async reAuthenticateOAuth(){try{let e=await this.retrieve();if(!e)return null;let{SinchAPI:n}=(K(),M(Fe)),s=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(s),s.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(ae.default.gray("Token expired, re-authenticating..."));let i=await this.reAuthenticateOAuth();return i?console.log(ae.default.green("\u2713 Token renewed successfully")):console.warn(ae.default.yellow("Failed to renew OAuth token. Please login again.")),i}return await this.getPassword(`${W}-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,s=process.env.SINCH_APPLICATION_SECRET;if(e&&n&&i&&s)return{projectId:process.env.SINCH_PROJECT_ID||this.config.get("projectId")||"",keyId:e,keySecret:n,applicationKey:i,applicationSecret:s};if(!this.config.get("credentialsStored"))return null;let r=this.config.get("projectId"),c=this.config.get("keyId"),d=this.config.get("defaultApplicationKey"),p=await this.getPassword(`${W}-keySecret`),u=d?await this.getPassword(d):null;return(!p||!u)&&(p=p||n||null,u=u||s||null),(!p||!u)&&(p=p||this.config.get("keySecretPlaintext"),u=u||this.config.get("applicationSecretPlaintext")),!p||!u?null:{projectId:r,keyId:c,keySecret:p,applicationKey:d,applicationSecret:u}}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(`${W}-keySecret`),await this.deletePassword(`${W}-oauth-access`),await this.deletePassword(`${W}-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(`${W}-keySecret`),s=this.config.get("defaultApplicationKey"),a=s?await this.getPassword(s):null;return!!(i&&a)}async hasOAuthToken(){return this.config.get("oauthStored")?!!await this.getPassword(`${W}-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(`${W}-basic-auth`,e)&&(this.config.set("basicAuthStored",!0),await this.config.save())}async getBasicAuthToken(){return this.config.get("basicAuthStored")?await this.getPassword(`${W}-basic-auth`):null}async clearBasicAuthToken(){await this.deletePassword(`${W}-basic-auth`),this.config.set("basicAuthStored",!1),await this.config.save()}}});var Pe={};Ke(Pe,{Config:()=>lt,config:()=>f});var X,We,nn,bt,lt,f,D=re(()=>{"use strict";X=m(require("fs-extra")),We=m(require("path")),nn=m(require("os")),bt=m(require("chalk"));tn();lt=class{configDir;configFile;projectConfigFile;_config=null;_projectConfig=null;_credentials=null;constructor(){this.configDir=We.join(nn.homedir(),".sinch"),this.configFile=We.join(this.configDir,"config.json"),this.projectConfigFile=We.join(process.cwd(),"sinch.json")}async load(){try{await X.ensureDir(this.configDir),await X.pathExists(this.configFile)?this._config=await X.readJson(this.configFile):(this._config=this._getDefaultConfig(),await this.save())}catch(e){console.warn(bt.default.yellow(`Warning: Could not load config: ${e.message}`)),this._config=this._getDefaultConfig()}this._credentials=new ct(this);try{await X.pathExists(this.projectConfigFile)&&(this._projectConfig=await X.readJson(this.projectConfigFile))}catch(e){console.warn(bt.default.yellow(`Warning: Could not load project config: ${e.message}`))}}async save(){try{await X.ensureDir(this.configDir),await X.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=We.join(process.cwd(),"sinch.json");await X.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={},s=null){let a={name:e,runtime:n,description:`Sinch Functions project: ${e}`,created:new Date().toISOString()};return i&&Object.keys(i).length>0&&(a.variables=i),s&&(a.applicationKey=s),this._projectConfig=a,await this.saveProjectConfig(),a}isInProject(){return this._projectConfig!==null}getProjectConfig(){return this._projectConfig}_getDefaultConfig(){return{apiUrl:"https://functions.api.sinch.com",oauthUrl:"https://auth.sinch.com/oauth2/token",projectId:"default-project",created:new Date().toISOString()}}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()}},f=new lt});var ee,ge,St,on,vt,t,_=re(()=>{"use strict";ee=m(require("chalk")),ge=m(require("fs")),St=m(require("path")),on=m(require("os")),vt=class{verbose;logFile;constructor(e={}){this.verbose=e.verbose||process.env.VERBOSE==="true";let n="cli";try{let i=St.join(process.cwd(),"sinch.json");ge.existsSync(i)&&(n=JSON.parse(ge.readFileSync(i,"utf8")).name||"cli")}catch{}this.logFile=St.join(on.tmpdir(),`sinch-${n}.log`);try{ge.writeFileSync(this.logFile,`=== Sinch CLI Debug Log - ${new Date().toISOString()} ===
6
+ `,{flag:"w"})}catch{}}writeToFile(e,n,...i){try{let a=`[${new Date().toISOString()}] ${e}: ${n} ${i.length>0?JSON.stringify(i):""}
7
+ `;ge.appendFileSync(this.logFile,a)}catch{}}info(e,...n){console.log(ee.default.blue("\u2139"),e,...n),this.writeToFile("INFO",e,...n)}success(e,...n){console.log(ee.default.green("\u2705"),e,...n),this.writeToFile("SUCCESS",e,...n)}warn(e,...n){console.log(ee.default.yellow("\u26A0\uFE0F "),e,...n),this.writeToFile("WARN",e,...n)}error(e,...n){console.log(ee.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(ee.default.gray("\u{1F41B}"),ee.default.gray(e),...n)}log(e,...n){console.log(e,...n)}title(e){console.log(ee.default.blue.bold(`
8
+ \u{1F3AF} ${e}`))}subtitle(e){console.log(ee.default.gray(`
9
+ ${e}`))}list(e,n={}){let{indent:i=" ",bullet:s="\u2022"}=n;e.forEach(a=>{console.log(`${i}${ee.default.gray(s)} ${a}`)})}calculateColumnWidths(e,n){let i=e.map(s=>s.length);return n.forEach(s=>{s.forEach((a,r)=>{i[r]=Math.max(i[r]??0,String(a).length)})}),i}table(e,n){let i=this.calculateColumnWidths(e,n),s=e.map((a,r)=>a.padEnd(i[r]??0)).join(" ");console.log(ee.default.bold(s)),console.log(ee.default.gray("-".repeat(s.length))),n.forEach(a=>{let r=a.map((c,d)=>String(c).padEnd(i[d]??0)).join(" ");console.log(r)})}newline(){console.log()}},t=new vt});var xe={};Ke(xe,{Spinner:()=>dt,spinner:()=>l});var sn,rn,dt,l,T=re(()=>{"use strict";sn=m(require("ora")),rn=m(require("cli-spinners")),dt=class{spinner=null;spinnerType=rn.default.dots;start(e){return this.spinner=(0,sn.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)}},l=new dt});var pn=F((Ys,dn)=>{"use strict";var J=m(require("fs-extra")),me=m(require("path")),G=m(require("chalk")),Ie=m(require("inquirer")),an=require("commander");D();_();T();K();var Le=require("child_process"),cn=m(require("adm-zip")),$t=m(require("keytar")),ln=new an.Command("init");ln.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 f.load();let n=process.cwd(),i=new j(f.getApiConfig()),s=e.runtime;s||(e.nonInteractive?s="node":s=(await Ie.default.prompt([{type:"list",name:"runtime",message:"Choose a runtime:",choices:[{name:"Node.js",value:"node"},{name:"C# (.NET)",value:"csharp"}],default:"node"}])).runtime),l.start(`Fetching available templates for ${s}...`);let a=await i.listRuntimeTemplates(s);if(l.stop(),!a.templates||a.templates.length===0)throw new Error(`No templates available for runtime '${s}'`);let r=o;if(!r)if(e.nonInteractive){let b=a.templates.filter(S=>S.name&&S.name.trim());if(b.length>0)r=b[0]?.name||"",t.info(`Using default template: ${r} (non-interactive mode)`);else throw new Error("No templates available")}else{let b=a.templates.filter(y=>y.name&&y.name.trim()).map(y=>({name:`${y.name} - ${(y.description||"No description available").substring(0,100)}`,value:y.name}));r=(await Ie.default.prompt([{type:"list",name:"selectedTemplate",message:"Choose a template:",choices:b,pageSize:10}])).selectedTemplate}let c=e.name;c||(e.nonInteractive?c=r:c=(await Ie.default.prompt([{type:"input",name:"name",message:"Function name:",default:r,validate:S=>!S||S.trim().length===0?"Function name is required":/^[a-z][a-z0-9-]*$/.test(S.trim())?!0:"Function name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens"}])).name.trim());let d=me.default.join(n,c);if(await J.default.pathExists(d)){let b=!1;if(e.nonInteractive?(b=!0,t.info(`Directory '${c}' already exists. Overwriting (non-interactive mode)...`)):b=(await Ie.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${c}' already exists. Overwrite?`,default:!1}])).overwrite,!b){t.info("Initialization cancelled");return}await J.default.remove(d)}await J.default.ensureDir(d);let p=a.templates.find(b=>b.name===r);if(!p){let b=a.templates.map(S=>S.name).join(", ");throw new Error(`Template '${r}' not found. Available templates: ${b}`)}let u=["node","csharp"];if(!u.includes(s))throw new Error(`Runtime '${s}' not supported. Supported runtimes: ${u.join(", ")}`);l.start(`\u{1F680} Initializing ${c} with ${r} template (${s})...`);let h=await i.downloadTemplate(s,r);new cn.default(h).extractAllTo(d,!0),l.succeed("\u{1F4E6} Template extracted");let w={},v=[],U=me.default.join(d,"template.json");if(await J.default.pathExists(U)){let b=await J.default.readJson(U);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[y,$]of Object.entries(b.variables)){let N;typeof $=="string"?N=$:N=$.default||"",w[y]=N,t.info(` ${y}: ${N}`)}}else{t.newline(),t.info("\u{1F4DD} Configure template variables:");for(let[y,$]of Object.entries(b.variables)){let N;typeof $=="string"?N={type:"input",name:y,message:`${y.replace(/_/g," ").toLowerCase()}:`,default:$}:(N={type:$.type==="number"?"number":"input",name:y,message:`${$.description||y.replace(/_/g," ").toLowerCase()}:`,default:$.default},$.type==="number"&&(N.validate=fe=>$.min!==void 0&&fe<$.min?`Value must be at least ${$.min}`:$.max!==void 0&&fe>$.max?`Value must be at most ${$.max}`:!0));let ve=await Ie.default.prompt([N]);w[y]=ve[y]}}let S="sinch-functions-cli";if(b.secrets&&Object.keys(b.secrets).length>0)if(v=Object.keys(b.secrets),e.nonInteractive){t.info("\u{1F4DD} Template secrets detected (non-interactive mode):");for(let y of Object.keys(b.secrets))t.info(` ${y}: [will need to be set manually]`)}else{t.newline(),t.info("\u{1F510} Configure template secrets (stored securely in OS keychain):");for(let[y,$]of Object.entries(b.secrets)){let N=$.description||y.replace(/_/g," ").toLowerCase(),ve=$.required!==!1,fe={type:"password",name:y,message:`${N}:`,validate:B=>ve&&(!B||B.trim()==="")?"This secret is required":!0},Be=(await Ie.default.prompt([fe]))[y];if(Be&&Be.trim()!=="")try{let B=`${c}-${y}`;await $t.default.setPassword(S,B,Be),t.info(` \u2705 ${y} stored securely in keychain`)}catch(B){t.warn(` \u26A0\uFE0F Could not store ${y} in keychain: ${B.message}`),t.info(` \u{1F4A1} You can add it later with: sinch secrets add ${y} <value>`)}}}await J.default.remove(U)}l.start("\u{1F527} Finalizing function configuration...");let Z=me.default.join(d,"sinch.json"),I;if(await J.default.pathExists(Z)){if(I=await J.default.readJson(Z),I.name=c,I.description=`Sinch Functions function: ${c}`,I.functionId=null,delete I.projectId,delete I.voiceAppId,I.variables)for(let[b,S]of Object.entries(I.variables))typeof S=="string"&&(S==="your-project-id"||S==="{{PROJECT_ID}}"?I.variables[b]=f.get("projectId"):(S==="your-application-key"||S==="{{SINCH_APPLICATION_KEY}}")&&(I.variables[b]=f.get("defaultApplicationKey")));I.created=new Date().toISOString(),I.variables={},I.secrets&&delete I.secrets}else I={name:c,functionId:null,runtime:s,description:`Sinch Functions function: ${c}`,created:new Date().toISOString(),variables:{},custom:{}};if(await J.default.writeJson(Z,I,{spaces:2}),s==="node"){let b=me.default.join(d,"package.json");if(await J.default.pathExists(b)){let P=await J.default.readJson(b);P.name=c,P.description=I.description,await J.default.writeJson(b,P,{spaces:2})}let S=me.default.join(d,".env"),y=`# Sinch Functions Environment Variables
10
10
  `;y+=`# Generated by sinch functions init
11
11
 
12
12
  `,y+=`# Template Variables
13
13
  `,Object.keys(w).forEach(P=>{y+=`${P}=${w[P]}
14
- `});let $=f.get("projectId"),R=f.get("functionId"),he=f.get("defaultApplicationKey"),ce=f.get("keyId");y+=`
14
+ `});let $=f.get("projectId"),N=f.get("functionId"),ve=f.get("defaultApplicationKey"),fe=f.get("keyId");y+=`
15
15
  # Sinch Configuration
16
16
  `,y+=`PROJECT_ID=${$||""}
17
- `,y+=`FUNCTION_ID=${R||""}
18
- `,y+=`PROJECT_ID_API_KEY=${ce||""}
19
- `,y+=`VOICE_APPLICATION_KEY=${he||""}
17
+ `,y+=`FUNCTION_ID=${N||""}
18
+ `,y+=`PROJECT_ID_API_KEY=${fe||""}
19
+ `,y+=`VOICE_APPLICATION_KEY=${ve||""}
20
20
  `,y+=`PROTECT_VOICE_CALLBACKS=deploy
21
21
  `,y+=`
22
22
  # Secrets (stored in OS keychain - use "sinch auth login" to configure)
@@ -30,115 +30,127 @@ ${e}`))}list(e,n={}){let{indent:o=" ",bullet:s="\u2022"}=n;e.forEach(r=>{consol
30
30
  `,y+=`NODE_ENV=development
31
31
  `,y+=`PORT=3000
32
32
  `,y+=`SINCH_TUNNEL=false
33
- `,await F.default.writeFile(S,y),t.info(""),t.info("\u{1F510} Secrets Management for Node.js:");try{let P=await f.getCredentials();P&&P.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(` ${q.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(` ${q.default.cyan("sinch auth login")}`),t.info(""),t.info(" To add custom secrets:"),t.info(` ${q.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`))}catch{t.info(" \u2139\uFE0F Set up authentication with:"),t.info(` ${q.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(s==="csharp"){let b=de.default.join(c,"appsettings.json"),S;await F.default.pathExists(b)?S=await F.default.readJson(b):S={Logging:{LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}},AllowedHosts:"*"},S.Logging||(S.Logging={LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}}),S.AllowedHosts||(S.AllowedHosts="*"),Object.keys(w).forEach(P=>{S[P]=w[P]});let y=f.get("projectId"),$=f.get("defaultApplicationKey"),R=f.get("keyId");S.PROJECT_ID=y||"",S.PROJECT_ID_API_KEY=R||"",S.PROJECT_ID_API_SECRET="",S.VOICE_APPLICATION_KEY=$||"",S.VOICE_APPLICATION_SECRET="",v.forEach(P=>{S[P]=""}),await F.default.writeJson(b,S,{spaces:2});let he=de.default.join(c,"appsettings.Development.json"),ce={Logging:{LogLevel:{Default:"Debug","Microsoft.AspNetCore":"Information"}},SinchTunnel:!1};await F.default.writeJson(he,ce,{spaces:2});try{let P=await f.getCredentials();await new Promise((N,z)=>{let Q=(0,je.spawn)("dotnet",["user-secrets","init"],{cwd:c,shell:!0});Q.on("close",ye=>ye===0?N():z(new Error("Failed to init user-secrets"))),Q.on("error",z)}),P&&P.keySecret&&await new Promise((N,z)=>{let Q=(0,je.spawn)("dotnet",["user-secrets","set","PROJECT_ID_API_SECRET",P.keySecret],{cwd:c,shell:!0});Q.on("close",ye=>ye===0?N():z(new Error("Failed to set API secret"))),Q.on("error",z)}),P&&P.applicationSecret&&await new Promise((N,z)=>{let Q=(0,je.spawn)("dotnet",["user-secrets","set","VOICE_APPLICATION_SECRET",P.applicationSecret],{cwd:c,shell:!0});Q.on("close",ye=>ye===0?N():z(new Error("Failed to set app secret"))),Q.on("error",z)});let Oe="sinch-functions-cli";for(let N of v)try{let z=`${u}-${N}`,Q=await ut.default.getPassword(Oe,z);Q&&await new Promise((ye,Dt)=>{let Ot=(0,je.spawn)("dotnet",["user-secrets","set",N,Q],{cwd:c,shell:!0});Ot.on("close",so=>so===0?ye():Dt(new Error(`Failed to set ${N}`))),Ot.on("error",Dt)})}catch{}(P&&(P.keySecret||P.applicationSecret)||v.length>0)&&(t.info(""),t.info("\u{1F510} Secrets Management for C#:"),t.info(" \u2705 User secrets have been configured automatically"),t.info(" You can view them with: "+q.default.cyan("dotnet user-secrets list")),v.length>0&&t.info(" \u{1F4A1} Template secrets have been added to user-secrets"))}catch{t.info(""),t.info("\u{1F510} Secrets Management for C#:"),t.info(" For local development, use dotnet user-secrets:"),t.info(` ${q.default.cyan("dotnet user-secrets init")}`),t.info(` ${q.default.cyan('dotnet user-secrets set "PROJECT_ID_API_SECRET" "your-api-secret"')}`),t.info(` ${q.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: ${q.default.cyan(u)}`),t.info(`Template: ${q.default.yellow(a)}`),t.info(`Runtime: ${q.default.blue(s)}`),t.info(`Location: ${q.default.gray(c)}`),s==="node"&&!e.skipInstall){t.newline(),d.start("Installing npm packages...");try{await new Promise((b,S)=>{let y=(0,je.spawn)("npm",["install"],{cwd:c,stdio:"inherit",shell:!0});y.on("close",$=>{$===0?b():S(new Error(`npm install failed with code ${$}`))}),y.on("error",$=>{S($)})}),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: ${q.default.cyan(`cd ${u}`)}`),s==="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 ${l.description}`),l.features&&l.features.length>0&&l.features.forEach(b=>{t.info(`\u2022 ${b}`)})}catch(n){d.stop(),t.error(`Failed to initialize function: ${n.message}`),process.exit(1)}});Mt.exports=Jt});var Qt=K((zi,zt)=>{"use strict";var I=h(require("chalk")),Ht=require("commander"),Gt=h(require("cli-table3")),Le=h(require("inquirer"));U();j();B();L();var Yt=new Ht.Command("list");Yt.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 i=>{try{await f.load();let e=new A(f.getApiConfig());d.start("\u{1F4CB} Loading functions...");let n={limit:parseInt(i.limit||"50")};i.status&&(n.status=i.status),i.runtime&&(n.runtime=i.runtime);let o=await e.listFunctions();if(d.succeed(`\u{1F4CB} Found ${o.functions.length} functions`),o.functions.length===0){t.newline(),t.info("No functions found"),t.info("\u{1F4A1} Create your first function with:"),t.info(` ${I.default.cyan("sinch functions init")}`);return}t.newline(),t.title("Functions:");let s=o.functions.map(a=>{let u=new Date(a.createdAt).toLocaleDateString(),c=dt(a.status),l=a.containerAppUrl?a.containerAppUrl.length>40?a.containerAppUrl.substring(0,37)+"...":a.containerAppUrl:I.default.gray("Not deployed");return[I.default.cyan(a.name),I.default.yellow(a.runtime),c,I.default.gray(u),I.default.blue(l)]}),r=new Gt.default({head:["Name","Runtime","Status","Created","URL"],style:{head:["cyan"]},colWidths:[20,10,15,12,45]});if(r.push(...s),console.log(r.toString()),o.pagination){let{page:a,totalCount:u,totalPages:c}=o.pagination;t.newline(),t.info(I.default.gray(`Page ${a} of ${c} (${u} total functions)`)),a<c&&t.info(I.default.gray("\u{1F4A1} Use --limit to see more results"))}if(i.interactive&&o.functions.length>0){t.newline();let a=o.functions.map(l=>({name:`${l.name.padEnd(20)} ${l.runtime.padEnd(8)} ${dt(l.status).padEnd(20)} ${l.id.substring(0,8)}`,value:l.id,short:l.name}));a.push(new Le.default.Separator),a.push({name:I.default.gray("Exit"),value:"exit",short:"Exit"});let{selectedFunction:u}=await Le.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function for actions:",choices:a,pageSize:15}]);if(u==="exit")return;let c=o.functions.find(l=>l.id===u);c&&await $o(c,e)}else t.newline(),t.info("\u{1F4A1} Function commands:"),t.info(` \u2022 View details: ${I.default.cyan("sinch functions status 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 View logs: ${I.default.cyan("sinch functions logs 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Download: ${I.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Interactive mode: ${I.default.cyan("sinch functions list -i")}`),t.info(` \u2022 Deploy new function: ${I.default.cyan("sinch functions deploy")}`)}catch(e){d.stop(),t.error(`Failed to list functions: ${e.message}`),process.exit(1)}});function dt(i){return{Running:I.default.green("\u2705 Running"),Failed:I.default.red("\u274C Failed"),Pending:I.default.yellow("\u23F3 Pending"),Building:I.default.blue("\u{1F528} Building")}[i]||I.default.gray(i)}async function $o(i,e){t.newline(),t.info(`\u{1F4CB} Selected: ${I.default.cyan(i.name)}`),t.info(` ID: ${I.default.gray(i.id)}`),t.info(` Status: ${dt(i.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:I.default.gray("Back"),value:"back"}]}]);switch(n){case"download":t.info(`
34
- \u{1F4A1} To download this function, run:`),t.info(` ${I.default.cyan(`sinch functions download ${i.id}`)}`);break;case"status":t.info(`
35
- \u{1F4A1} To view status, run:`),t.info(` ${I.default.cyan(`sinch functions status ${i.id}`)}`);break;case"logs":t.info(`
36
- \u{1F4A1} To view logs, run:`),t.info(` ${I.default.cyan(`sinch functions logs ${i.id}`)}`);break;case"copy-url":i.containerAppUrl?(await require("clipboardy").write(i.containerAppUrl),t.success(`\u2705 URL copied to clipboard: ${i.containerAppUrl}`)):t.warn("\u26A0\uFE0F Function has no URL (not deployed)");break;case"delete":t.info(`
37
- \u{1F4A1} To delete this function, run:`),t.info(` ${I.default.cyan(`sinch functions delete ${i.id}`)}`);break;case"back":return}}zt.exports=Yt});async function ft(i){if(!await f.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let e=await f.getApplicationCredentials();if(!e)throw new Error('No application credentials found. Run "sinch auth login" first.');let o=`https://callingapi.sinch.com/v1/configuration/callbacks/applications/${e.applicationKey}/`,s={url:{primary:i}},r=`${e.applicationKey}:${e.applicationSecret}`,a=Buffer.from(r).toString("base64");await pt.default.post(o,s,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/json"},timeout:1e4}),await new Promise(p=>setTimeout(p,1e3));let l=(await pt.default.get(o,{headers:{Authorization:`Basic ${a}`},timeout:1e4})).data?.url?.primary;if(l!==i)throw t.debug(`Callback verification mismatch. Expected: ${i}, Got: ${l}`),new Error(`Callback URL update verification failed. Expected: ${i}, Got: ${l}`);t.debug("Voice callback URL successfully updated and verified")}var pt,Zt=le(()=>{"use strict";pt=h(require("axios"));j();B()});function ko(){return"https://us.conversation.api.sinch.com"}async function Po(i,e,n){let o="https://auth.sinch.com/oauth2/token",s=new URLSearchParams;s.append("grant_type","client_credentials");let r=`${e}:${n}`,a=Buffer.from(r).toString("base64");return(await xe.default.post(o,s,{headers:{Authorization:`Basic ${a}`,"Content-Type":"application/x-www-form-urlencoded"},timeout:1e4})).data.access_token}async function Xe(){let i=Ne.default.join(process.cwd(),"appsettings.json");if(await re.default.pathExists(i))try{let n=await re.default.readJson(i);if(n.Webhooks?.AutoConfigureConversation!==!0)return{isConversation:!1};let o=n.CONVERSATION_APP_ID;if(o)return{isConversation:!0,appId:o}}catch(n){t.debug("Could not read appsettings.json: "+n.message)}let e=Ne.default.join(process.cwd(),".env");if(await re.default.pathExists(e))try{let n=await re.default.readFile(e,"utf8"),o={};if(n.split(`
38
- `).forEach(r=>{if(r.trim()&&!r.trim().startsWith("#")){let[a,...u]=r.split("=");a&&(o[a.trim()]=u.join("=").trim())}}),o.AUTO_CONFIGURE_CONVERSATION!=="true")return{isConversation:!1};let s=o.CONVERSATION_APP_ID;if(s)return{isConversation:!0,appId:s}}catch(n){t.debug("Could not read .env file: "+n.message)}return{isConversation:!1}}async function gt(i){if(!await f.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let{isConversation:e,appId:n}=await Xe();if(t.debug(`isConversationFunction check: isConversation=${e}, appId=${n}`),!e||!n){t.debug("Not a Conversation function or missing CONVERSATION_APP_ID, skipping webhook config");return}let o=await f.getCredentials();if(!o?.projectId||!o?.keyId||!o?.keySecret)throw new Error('Missing project credentials. Run "sinch auth login" first.');let s=ko(),r=`${i}/conversation`;t.debug(`Conversation webhook URL: ${r}`),t.debug(`Project ID: ${o.projectId}, App ID: ${n}`),t.debug("Getting OAuth access token...");let a=await Po(o.projectId,o.keyId,o.keySecret);t.debug("Got access token successfully");let u={Authorization:`Bearer ${a}`,"Content-Type":"application/json"},c=`${s}/v1/projects/${o.projectId}/apps/${n}/webhooks`;t.debug(`Listing webhooks: GET ${c}`);let l=await xe.default.get(c,{headers:u,timeout:1e4});t.debug(`Found ${l.data.webhooks?.length||0} webhooks`);let p=l.data.webhooks?.find(v=>v.target?.includes(".sinch.com")&&(v.target?.includes("fn-dev.")||v.target?.includes("fn-prod.")||v.target?.includes("functions."))),m=["MESSAGE_INBOUND"];if(p){t.debug(`Found existing webhook: id=${p.id}, target=${p.target}`);let v=`${s}/v1/projects/${o.projectId}/webhooks/${p.id}`;t.debug(`Deleting webhook: DELETE ${v}`);try{await xe.default.delete(v,{headers:u,timeout:1e4}),t.debug(`Deleted existing Conversation webhook ${p.id}`)}catch(O){t.debug(`Failed to delete webhook: ${O.response?.status} ${O.response?.data?JSON.stringify(O.response.data):O.message}`)}}let C=`${s}/v1/projects/${o.projectId}/webhooks`,w={app_id:n,target:r,target_type:"HTTP",triggers:m};t.debug(`Creating webhook: POST ${C}`),t.debug(`Payload: ${JSON.stringify(w)}`);try{let v=await xe.default.post(C,w,{headers:u,timeout:1e4});t.debug(`Created new Conversation webhook: ${JSON.stringify(v.data)}`)}catch(v){throw t.debug(`Failed to create webhook: ${v.response?.status} ${v.response?.data?JSON.stringify(v.response.data):v.message}`),v}t.debug("Conversation webhook successfully configured")}async function mt(){let i=Ne.default.join(process.cwd(),"appsettings.json");if(await re.default.pathExists(i))try{let n=await re.default.readJson(i);return n.Webhooks?n.Webhooks.AutoConfigureVoice===!0:!0}catch(n){t.debug("Could not read appsettings.json: "+n.message)}let e=Ne.default.join(process.cwd(),".env");if(await re.default.pathExists(e))try{let n=await re.default.readFile(e,"utf8"),o={};return n.split(`
39
- `).forEach(r=>{if(r.trim()&&!r.trim().startsWith("#")){let[a,...u]=r.split("=");a&&(o[a.trim()]=u.join("=").trim())}}),Object.keys(o).some(r=>r.startsWith("AUTO_CONFIGURE_"))?o.AUTO_CONFIGURE_VOICE==="true":!0}catch(n){t.debug("Could not read .env file: "+n.message)}return!0}var xe,re,Ne,Xt=le(()=>{"use strict";xe=h(require("axios")),re=h(require("fs-extra")),Ne=h(require("path"));j();B()});var on={};He(on,{combineDocumentation:()=>tn,detectRuntimeFromFile:()=>nn,findFunctionFile:()=>en,generateDocsFromLocal:()=>ht,saveDocumentationToFile:()=>yt});async function ht(){let i=process.cwd(),e=await en(i);if(!e)throw new Error("No function file found. Make sure you're in a function directory with function.js, function.ts, index.js, index.ts, handler.js, or handler.ts");let n=await Te.readFile(e,"utf8"),o=nn(e),s=pe.basename(i),a=await new A(f.getApiConfig()).generateDocumentationFromCode(n,o,s);return tn(a)}async function en(i){let e=["function.js","function.ts","index.js","index.ts","handler.js","handler.ts","function.py","handler.py","Function.cs","Handler.cs"];for(let n of e){let o=pe.join(i,n);if(await Te.pathExists(o))return o}return null}function tn(i){let e=i.documentation||"",n=i.diagram||i.callFlowDiagram;return n&&(e&&!e.endsWith(`
33
+ `,await J.default.writeFile(S,y),t.info(""),t.info("\u{1F510} Secrets Management for Node.js:");try{let P=await f.getCredentials();P&&P.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(` ${G.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(` ${G.default.cyan("sinch auth login")}`),t.info(""),t.info(" To add custom secrets:"),t.info(` ${G.default.cyan("sinch functions secrets add <KEY> <VALUE>")}`))}catch{t.info(" \u2139\uFE0F Set up authentication with:"),t.info(` ${G.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(s==="csharp"){let b=me.default.join(d,"appsettings.json"),S;await J.default.pathExists(b)?S=await J.default.readJson(b):S={Logging:{LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}},AllowedHosts:"*"},S.Logging||(S.Logging={LogLevel:{Default:"Information","Microsoft.AspNetCore":"Warning"}}),S.AllowedHosts||(S.AllowedHosts="*"),Object.keys(w).forEach(P=>{S[P]=w[P]});let y=f.get("projectId"),$=f.get("defaultApplicationKey"),N=f.get("keyId");S.PROJECT_ID=y||"",S.PROJECT_ID_API_KEY=N||"",S.PROJECT_ID_API_SECRET="",S.VOICE_APPLICATION_KEY=$||"",S.VOICE_APPLICATION_SECRET="",v.forEach(P=>{S[P]=""}),await J.default.writeJson(b,S,{spaces:2});let ve=me.default.join(d,"appsettings.Development.json"),fe={Logging:{LogLevel:{Default:"Debug","Microsoft.AspNetCore":"Information"}},SinchTunnel:!1};await J.default.writeJson(ve,fe,{spaces:2});try{let P=await f.getCredentials();await new Promise((B,te)=>{let ne=(0,Le.spawn)("dotnet",["user-secrets","init"],{cwd:d,shell:!0});ne.on("close",$e=>$e===0?B():te(new Error("Failed to init user-secrets"))),ne.on("error",te)}),P&&P.keySecret&&await new Promise((B,te)=>{let ne=(0,Le.spawn)("dotnet",["user-secrets","set","PROJECT_ID_API_SECRET",P.keySecret],{cwd:d,shell:!0});ne.on("close",$e=>$e===0?B():te(new Error("Failed to set API secret"))),ne.on("error",te)}),P&&P.applicationSecret&&await new Promise((B,te)=>{let ne=(0,Le.spawn)("dotnet",["user-secrets","set","VOICE_APPLICATION_SECRET",P.applicationSecret],{cwd:d,shell:!0});ne.on("close",$e=>$e===0?B():te(new Error("Failed to set app secret"))),ne.on("error",te)});let Be="sinch-functions-cli";for(let B of v)try{let te=`${c}-${B}`,ne=await $t.default.getPassword(Be,te);ne&&await new Promise(($e,zt)=>{let Qt=(0,Le.spawn)("dotnet",["user-secrets","set",B,ne],{cwd:d,shell:!0});Qt.on("close",ei=>ei===0?$e():zt(new Error(`Failed to set ${B}`))),Qt.on("error",zt)})}catch{}(P&&(P.keySecret||P.applicationSecret)||v.length>0)&&(t.info(""),t.info("\u{1F510} Secrets Management for C#:"),t.info(" \u2705 User secrets have been configured automatically"),t.info(" You can view them with: "+G.default.cyan("dotnet user-secrets list")),v.length>0&&t.info(" \u{1F4A1} Template secrets have been added to user-secrets"))}catch{t.info(""),t.info("\u{1F510} Secrets Management for C#:"),t.info(" For local development, use dotnet user-secrets:"),t.info(` ${G.default.cyan("dotnet user-secrets init")}`),t.info(` ${G.default.cyan('dotnet user-secrets set "PROJECT_ID_API_SECRET" "your-api-secret"')}`),t.info(` ${G.default.cyan('dotnet user-secrets set "VOICE_APPLICATION_SECRET" "your-app-secret"')}`)}}if(l.succeed("\u{1F680} Function initialized successfully"),t.newline(),t.title(`Function: ${G.default.cyan(c)}`),t.info(`Template: ${G.default.yellow(r)}`),t.info(`Runtime: ${G.default.blue(s)}`),t.info(`Location: ${G.default.gray(d)}`),s==="node"&&!e.skipInstall){t.newline(),l.start("Installing npm packages...");try{await new Promise((b,S)=>{let y=(0,Le.spawn)("npm",["install"],{cwd:d,stdio:"inherit",shell:!0});y.on("close",$=>{$===0?b():S(new Error(`npm install failed with code ${$}`))}),y.on("error",$=>{S($)})}),l.succeed("\u{1F4E6} Dependencies installed successfully")}catch(b){l.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: ${G.default.cyan(`cd ${c}`)}`),s==="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 ${p.description}`),p.features&&p.features.length>0&&p.features.forEach(b=>{t.info(`\u2022 ${b}`)})}catch(n){l.stop(),t.error(`Failed to initialize function: ${n.message}`),process.exit(1)}});dn.exports=ln});var hn=F((er,mn)=>{"use strict";var A=m(require("chalk")),un=require("commander"),fn=m(require("cli-table3")),Ge=m(require("inquirer"));K();D();_();T();var gn=new un.Command("list");gn.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 f.load();let e=new j(f.getApiConfig());l.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(l.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(` ${A.default.cyan("sinch functions init")}`);return}t.newline(),t.title("Functions:");let s=i.functions.map(r=>{let c=new Date(r.createdAt).toLocaleDateString(),d=kt(r.status),p=r.containerAppUrl?r.containerAppUrl.length>40?r.containerAppUrl.substring(0,37)+"...":r.containerAppUrl:A.default.gray("Not deployed");return[A.default.cyan(r.name),A.default.yellow(r.runtime),d,A.default.gray(c),A.default.blue(p)]}),a=new fn.default({head:["Name","Runtime","Status","Created","URL"],style:{head:["cyan"]},colWidths:[20,10,15,12,45]});if(a.push(...s),console.log(a.toString()),i.pagination){let{page:r,totalCount:c,totalPages:d}=i.pagination;t.newline(),t.info(A.default.gray(`Page ${r} of ${d} (${c} total functions)`)),r<d&&t.info(A.default.gray("\u{1F4A1} Use --limit to see more results"))}if(o.interactive&&i.functions.length>0){t.newline();let r=i.functions.map(p=>({name:`${p.name.padEnd(20)} ${p.runtime.padEnd(8)} ${kt(p.status).padEnd(20)} ${p.id.substring(0,8)}`,value:p.id,short:p.name}));r.push(new Ge.default.Separator),r.push({name:A.default.gray("Exit"),value:"exit",short:"Exit"});let{selectedFunction:c}=await Ge.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function for actions:",choices:r,pageSize:15}]);if(c==="exit")return;let d=i.functions.find(p=>p.id===c);d&&await yi(d,e)}else t.newline(),t.info("\u{1F4A1} Function commands:"),t.info(` \u2022 View details: ${A.default.cyan("sinch functions status 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 View logs: ${A.default.cyan("sinch functions logs 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Download: ${A.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABC")}`),t.info(` \u2022 Interactive mode: ${A.default.cyan("sinch functions list -i")}`),t.info(` \u2022 Deploy new function: ${A.default.cyan("sinch functions deploy")}`)}catch(e){l.stop(),t.error(`Failed to list functions: ${e.message}`),process.exit(1)}});function kt(o){return{Running:A.default.green("\u2705 Running"),Failed:A.default.red("\u274C Failed"),Pending:A.default.yellow("\u23F3 Pending"),Building:A.default.blue("\u{1F528} Building")}[o]||A.default.gray(o)}async function yi(o,e){t.newline(),t.info(`\u{1F4CB} Selected: ${A.default.cyan(o.name)}`),t.info(` ID: ${A.default.gray(o.id)}`),t.info(` Status: ${kt(o.status)}`),t.newline();let{action:n}=await Ge.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 Ge.default.Separator,{name:A.default.gray("Back"),value:"back"}]}]);switch(n){case"download":t.info(`
34
+ \u{1F4A1} To download this function, run:`),t.info(` ${A.default.cyan(`sinch functions download ${o.id}`)}`);break;case"status":t.info(`
35
+ \u{1F4A1} To view status, run:`),t.info(` ${A.default.cyan(`sinch functions status ${o.id}`)}`);break;case"logs":t.info(`
36
+ \u{1F4A1} To view logs, run:`),t.info(` ${A.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(`
37
+ \u{1F4A1} To delete this function, run:`),t.info(` ${A.default.cyan(`sinch functions delete ${o.id}`)}`);break;case"back":return}}mn.exports=gn});async function It(o){if(!await f.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let e=await f.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}/`,s={url:{primary:o}},a=`${e.applicationKey}:${e.applicationSecret}`,r=Buffer.from(a).toString("base64");await Pt.default.post(i,s,{headers:{Authorization:`Basic ${r}`,"Content-Type":"application/json"},timeout:1e4}),await new Promise(u=>setTimeout(u,1e3));let p=(await Pt.default.get(i,{headers:{Authorization:`Basic ${r}`},timeout:1e4})).data?.url?.primary;if(p!==o)throw t.debug(`Callback verification mismatch. Expected: ${o}, Got: ${p}`),new Error(`Callback URL update verification failed. Expected: ${o}, Got: ${p}`);t.debug("Voice callback URL successfully updated and verified")}var Pt,yn=re(()=>{"use strict";Pt=m(require("axios"));D();_()});function wi(){return"https://us.conversation.api.sinch.com"}async function Ci(o,e,n){let i="https://auth.sinch.com/oauth2/token",s=new URLSearchParams;s.append("grant_type","client_credentials");let a=`${e}:${n}`,r=Buffer.from(a).toString("base64");return(await He.default.post(i,s,{headers:{Authorization:`Basic ${r}`,"Content-Type":"application/x-www-form-urlencoded"},timeout:1e4})).data.access_token}async function pt(){let o=Ye.default.join(process.cwd(),"appsettings.json");if(await pe.default.pathExists(o))try{let n=await pe.default.readJson(o);if(n.Webhooks?.AutoConfigureConversation!==!0)return{isConversation:!1};let i=n.CONVERSATION_APP_ID;if(i)return{isConversation:!0,appId:i}}catch(n){t.debug("Could not read appsettings.json: "+n.message)}let e=Ye.default.join(process.cwd(),".env");if(await pe.default.pathExists(e))try{let n=await pe.default.readFile(e,"utf8"),i={};if(n.split(`
38
+ `).forEach(a=>{if(a.trim()&&!a.trim().startsWith("#")){let[r,...c]=a.split("=");r&&(i[r.trim()]=c.join("=").trim())}}),i.AUTO_CONFIGURE_CONVERSATION!=="true")return{isConversation:!1};let s=i.CONVERSATION_APP_ID;if(s)return{isConversation:!0,appId:s}}catch(n){t.debug("Could not read .env file: "+n.message)}return{isConversation:!1}}async function At(o){if(!await f.hasCredentials())throw new Error('No Sinch credentials found. Run "sinch auth login" first.');let{isConversation:e,appId:n}=await pt();if(t.debug(`isConversationFunction check: isConversation=${e}, appId=${n}`),!e||!n){t.debug("Not a Conversation function or missing CONVERSATION_APP_ID, skipping webhook config");return}let i=await f.getCredentials();if(!i?.projectId||!i?.keyId||!i?.keySecret)throw new Error('Missing project credentials. Run "sinch auth login" first.');let s=wi(),a=`${o}/conversation`;t.debug(`Conversation webhook URL: ${a}`),t.debug(`Project ID: ${i.projectId}, App ID: ${n}`),t.debug("Getting OAuth access token...");let r=await Ci(i.projectId,i.keyId,i.keySecret);t.debug("Got access token successfully");let c={Authorization:`Bearer ${r}`,"Content-Type":"application/json"},d=`${s}/v1/projects/${i.projectId}/apps/${n}/webhooks`;t.debug(`Listing webhooks: GET ${d}`);let p=await He.default.get(d,{headers:c,timeout:1e4});t.debug(`Found ${p.data.webhooks?.length||0} webhooks`);let u=p.data.webhooks?.find(v=>v.target?.includes(".sinch.com")&&(v.target?.includes("fn-dev.")||v.target?.includes("fn-prod.")||v.target?.includes("functions."))),h=["MESSAGE_INBOUND"];if(u){t.debug(`Found existing webhook: id=${u.id}, target=${u.target}`);let v=`${s}/v1/projects/${i.projectId}/webhooks/${u.id}`;t.debug(`Deleting webhook: DELETE ${v}`);try{await He.default.delete(v,{headers:c,timeout:1e4}),t.debug(`Deleted existing Conversation webhook ${u.id}`)}catch(U){t.debug(`Failed to delete webhook: ${U.response?.status} ${U.response?.data?JSON.stringify(U.response.data):U.message}`)}}let C=`${s}/v1/projects/${i.projectId}/webhooks`,w={app_id:n,target:a,target_type:"HTTP",triggers:h};t.debug(`Creating webhook: POST ${C}`),t.debug(`Payload: ${JSON.stringify(w)}`);try{let v=await He.default.post(C,w,{headers:c,timeout:1e4});t.debug(`Created new Conversation webhook: ${JSON.stringify(v.data)}`)}catch(v){throw t.debug(`Failed to create webhook: ${v.response?.status} ${v.response?.data?JSON.stringify(v.response.data):v.message}`),v}t.debug("Conversation webhook successfully configured")}async function Et(){let o=Ye.default.join(process.cwd(),"appsettings.json");if(await pe.default.pathExists(o))try{let n=await pe.default.readJson(o);return n.Webhooks?n.Webhooks.AutoConfigureVoice===!0:!0}catch(n){t.debug("Could not read appsettings.json: "+n.message)}let e=Ye.default.join(process.cwd(),".env");if(await pe.default.pathExists(e))try{let n=await pe.default.readFile(e,"utf8"),i={};return n.split(`
39
+ `).forEach(a=>{if(a.trim()&&!a.trim().startsWith("#")){let[r,...c]=a.split("=");r&&(i[r.trim()]=c.join("=").trim())}}),Object.keys(i).some(a=>a.startsWith("AUTO_CONFIGURE_"))?i.AUTO_CONFIGURE_VOICE==="true":!0}catch(n){t.debug("Could not read .env file: "+n.message)}return!0}var He,pe,Ye,wn=re(()=>{"use strict";He=m(require("axios")),pe=m(require("fs-extra")),Ye=m(require("path"));D();_()});var vn={};Ke(vn,{combineDocumentation:()=>bn,detectRuntimeFromFile:()=>Sn,findFunctionFile:()=>Cn,generateDocsFromLocal:()=>jt,saveDocumentationToFile:()=>Rt});async function jt(){let o=process.cwd(),e=await Cn(o);if(!e)throw new Error("No function file found. Make sure you're in a function directory with function.js, function.ts, index.js, index.ts, handler.js, or handler.ts");let n=await Ue.readFile(e,"utf8"),i=Sn(e),s=he.basename(o),r=await new j(f.getApiConfig()).generateDocumentationFromCode(n,i,s);return bn(r)}async function Cn(o){let e=["function.js","function.ts","index.js","index.ts","handler.js","handler.ts","function.py","handler.py","Function.cs","Handler.cs"];for(let n of e){let i=he.join(o,n);if(await Ue.pathExists(i))return i}return null}function bn(o){let e=o.documentation||"",n=o.diagram||o.callFlowDiagram;return n&&(e&&!e.endsWith(`
40
40
 
41
41
  `)&&(e+=`
42
42
 
43
43
  `),e+=`## Call Flow Diagram
44
44
 
45
- `,e+="```mermaid\n",e+=n.replace(/^```mermaid\n?|```$/g,""),e+="\n```\n"),i.generatedAt&&(e+=`
45
+ `,e+="```mermaid\n",e+=n.replace(/^```mermaid\n?|```$/g,""),e+="\n```\n"),o.generatedAt&&(e+=`
46
46
  ---
47
47
 
48
- `,e+=`*Documentation generated on ${new Date(i.generatedAt).toLocaleString()} using Sinch AI*
49
- `),e}async function yt(i,e){let n=pe.resolve(e);await Te.writeFile(n,i,"utf8")}function nn(i){switch(pe.extname(i).toLowerCase()){case".js":case".ts":return"node";case".py":return"python";case".cs":return"csharp";default:return"node"}}var Te,pe,wt=le(()=>{"use strict";Te=h(require("fs-extra")),pe=h(require("path"));U();j()});var pn=K((ps,dn)=>{"use strict";var Z=h(require("fs-extra")),Se=h(require("path")),k=h(require("chalk")),rn=require("commander");U();j();B();L();Zt();Xt();var an=h(require("adm-zip")),cn=h(require("os")),Ct=h(require("inquirer")),Ue=require("child_process"),ln=h(require("keytar")),un=new rn.Command("deploy");un.description("Deploy function to production").option("-n, --name <name>","Function name (default: current directory)").option("--no-wait","Don't wait for deployment to complete").option("--non-interactive","Use default values without prompting (auto-generates docs)").option("--no-docs","no doc generation").option("--private","Deploy to private namespace (internal access only, not publicly accessible)").action(async i=>{try{if(await f.load(),!f.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=f.getProjectConfig(),n=i.name||e.name,o=e.runtime;if(await Ro(e,i),o==="csharp"){let p=await Z.default.readdir(process.cwd()).then(C=>C.filter(w=>w.endsWith(".csproj")));if(p.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");let m=p[0];await Do(process.cwd(),m)}d.start("\u{1F4E6} Packaging function...");let s=await Eo(n);d.succeed("\u{1F4E6} Function packaged"),d.start("\u{1F527} Preparing configuration...");let r=await Io(o,n);d.succeed("\u{1F527} Configuration prepared");let a=await To(e,i);d.start("\u{1F680} Submitting deployment...");let u=new A(f.getApiConfig()),c=await Z.default.readFile(s),l=await u.deployFunction(n,o,c,r,a);if(await Z.default.remove(s),d.succeed("\u{1F680} Deployment submitted"),f.set("functionId",l.id,!0),await f.saveProjectConfig(),t.newline(),t.info(`Function ID: ${k.default.cyan(l.id)}`),t.info(`Status: ${bt(l.status)}`),i.wait===!1){t.newline(),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${k.default.cyan(`sinch functions status ${l.id}`)}`);return}await Ao(u,l.id)}catch(e){d.stop(),t.error(`Failed to deploy function: ${e.message}`),process.exit(1)}});async function Eo(i){let e=new an.default,n=process.cwd(),o=Se.default.join(cn.default.tmpdir(),`${i}-${Date.now()}.zip`),s=["node_modules","bin","obj",".git",".DS_Store","*.zip",".env",".env.local","npm-debug.log*",".sinch-tmp","examples","claude.md","readme.md",".vs",".vscode",".idea",".cursor","*.user","*.suo"];async function r(a,u=""){let c=await Z.default.readdir(a);for(let l of c){let p=Se.default.join(a,l),m=Se.default.join(u,l).replace(/\\/g,"/");if(s.some(w=>l.match(new RegExp(w.replace("*",".*")))))continue;if((await Z.default.stat(p)).isDirectory())await r(p,m);else{let w=await Z.default.readFile(p);e.addFile(m,w)}}}return await r(n),e.writeZip(o),o}async function Io(i,e){let n={},o=null;try{o=await f.getCredentials()}catch(s){t.debug("Could not load credentials from secure storage: "+s.message)}if(i==="csharp"){let s=Se.default.join(process.cwd(),"appsettings.json");if(await Z.default.pathExists(s))try{let r=await Z.default.readJson(s);for(let a of Object.keys(r)){if(a==="Logging"||a==="AllowedHosts")continue;let u=r[a];if(u===""||u===null||u===void 0){let c="",l=!1;try{let m=(0,Ue.execSync)("dotnet user-secrets list",{cwd:process.cwd(),encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim().split(`
50
- `);for(let C of m){let w=C.match(/^([^=]+)\s*=\s*(.+)$/);if(w&&w[1]&&w[2]&&w[1].trim()===a){c=w[2].trim(),l=!0,t.debug(`Found ${a} in dotnet user-secrets`);break}}}catch{}!c&&o&&(a==="PROJECT_ID"&&o.projectId?c=o.projectId:a==="PROJECT_ID_API_KEY"&&o.keyId?c=o.keyId:a==="PROJECT_ID_API_SECRET"&&o.keySecret?(c=o.keySecret,l=!0):a==="VOICE_APPLICATION_KEY"&&o.applicationKey?c=o.applicationKey:a==="VOICE_APPLICATION_SECRET"&&o.applicationSecret&&(c=o.applicationSecret,l=!0)),c&&(n[a]={Value:c,Secret:l})}else n[a]={Value:String(u),Secret:!1}}}catch(r){t.debug("Could not read appsettings.json: "+r.message)}}else{let s=Se.default.join(process.cwd(),".env");if(await Z.default.pathExists(s))try{let r=await Z.default.readFile(s,"utf8"),a={};r.split(`
51
- `).forEach(c=>{if(c.trim()&&!c.trim().startsWith("#")){let[l,...p]=c.split("=");l&&(a[l.trim()]=p.join("=").trim())}});let u=["PORT","NODE_ENV","SINCH_TUNNEL"];for(let[c,l]of Object.entries(a))if(!u.includes(c))if(l===""||l===null||l===void 0){let p="",m=!1;if(o&&(c==="PROJECT_ID"&&o.projectId?p=o.projectId:c==="PROJECT_ID_API_KEY"&&o.keyId?p=o.keyId:c==="PROJECT_ID_API_SECRET"&&o.keySecret?(p=o.keySecret,m=!0):c==="VOICE_APPLICATION_KEY"&&o.applicationKey?p=o.applicationKey:c==="VOICE_APPLICATION_SECRET"&&o.applicationSecret&&(p=o.applicationSecret,m=!0)),!p)try{let C="sinch-functions-cli",w=`${e}-${c}`;p=await ln.default.getPassword(C,w)||"",p&&(m=!0,t.debug(`Loaded custom secret ${c} from keychain`))}catch(C){t.debug(`Could not load ${c} from keychain: ${C.message}`)}p&&(n[c]={Value:p,Secret:m})}else n[c]={Value:l,Secret:!1}}catch(r){t.debug("Could not read .env file: "+r.message)}}return n}async function Ao(i,e){let o=Date.now(),s=!1,r;return t.newline(),d.start("\u23F3 Connecting to deployment stream..."),new Promise((a,u)=>{let c,l;i.streamDeployment(e,p=>{let m=Math.floor((Date.now()-o)/1e3);switch(p.type){case"connected":d.text="\u23F3 Deployment stream connected, waiting for updates...";break;case"status":let C=p.data.data.message;d.text=`\u23F3 ${C} (${m}s)`;break;case"progress":let w=p.data.data.message,v=p.data.data.percentComplete;v?d.text=`\u23F3 ${w} (${v}%, ${m}s)`:d.text=`\u23F3 ${w} (${m}s)`;break;case"completed":s=!0,r=p.data.data.url,d.succeed("\u2705 Function deployed successfully"),i.getFunction(e).then(async H=>{if(t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${k.default.cyan(H.name)}`),t.info(` Status: ${bt("Running")}`),t.info(` URL: ${k.default.blue(r)}`),r){let E=await Xe(),b=await mt();if(E.isConversation){t.newline(),t.info("\u{1F4AC} Conversation Integration:");try{d.start("Updating Sinch Conversation webhook..."),await gt(r),d.succeed("Conversation webhook updated automatically"),t.info(` Webhook URL set to: ${k.default.cyan(r+"/conversation")}`)}catch(S){d.fail("Failed to update Conversation webhook");let y=S.response?.data?JSON.stringify(S.response.data):S.message;t.warn(` Error: ${y}`)}}if(b){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{d.start("Updating Sinch Voice callback URL..."),await ft(r),d.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${k.default.cyan(r)}`)}catch(S){d.fail("Failed to update callback URL automatically"),t.warn(` Error: ${S.message}`),t.info(` Manual setup: ${k.default.cyan(`sinch voice callback-url ${r}`)}`)}}t.info(` Test function: ${k.default.cyan(`curl ${r}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${k.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${k.default.cyan(`sinch functions status ${e}`)}`),c&&c(),l&&clearTimeout(l),a()}).catch(H=>{t.error(`Failed to get function details: ${H.message}`),c&&c(),l&&clearTimeout(l),a()});break;case"failed":s=!0;let O=p.data.data.errorMessage;d.fail("\u274C Deployment failed"),t.newline(),t.error("Deployment failed:"),O&&t.error(` ${O}`),t.newline(),t.info("\u{1F4A1} Troubleshooting:"),t.info(` \u2022 Check logs: ${k.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${k.default.cyan(`sinch functions status ${e}`)}`),c&&c(),l&&clearTimeout(l),process.exit(1);break}},p=>{t.debug("SSE stream error, falling back to polling:",p),d.text="\u23F3 Deployment stream unavailable, checking status...",c&&c(),sn(i,e,o,3e5).then(a).catch(u)}).then(p=>{t.debug("SSE stream setup successful, cleanup function received"),c=p,l=setTimeout(()=>{s||(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(` ${k.default.cyan(`sinch functions status ${e}`)}`),c&&c(),a())},3e5)}).catch(p=>{t.debug(`Failed to set up SSE stream, falling back to polling: ${p.message}`),sn(i,e,o,3e5).then(a).catch(u)})})}async function sn(i,e,n,o){for(;Date.now()-n<o;){try{let a=(await i.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: ${k.default.cyan(a.name)}`),t.info(` Status: ${bt(a.status)}`),t.info(` URL: ${k.default.blue(a.containerAppUrl)}`),a.containerAppUrl){let c=await Xe(),l=await mt();if(c.isConversation){t.newline(),t.info("\u{1F4AC} Conversation Integration:");try{d.start("Updating Sinch Conversation webhook..."),await gt(a.containerAppUrl),d.succeed("Conversation webhook updated automatically"),t.info(` Webhook URL set to: ${k.default.cyan(a.containerAppUrl+"/conversation")}`)}catch(p){d.fail("Failed to update Conversation webhook");let m=p.response?.data?JSON.stringify(p.response.data):p.message;t.warn(` Error: ${m}`)}}if(l){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{d.start("Updating Sinch Voice callback URL..."),await ft(a.containerAppUrl),d.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${k.default.cyan(a.containerAppUrl)}`)}catch(p){d.fail("Failed to update callback URL automatically"),t.warn(` Error: ${p.message}`),t.info(` Manual setup: ${k.default.cyan(`sinch voice callback-url ${a.containerAppUrl}`)}`)}}t.info(` Test function: ${k.default.cyan(`curl ${a.containerAppUrl}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${k.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${k.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: ${k.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${k.default.cyan(`sinch functions status ${e}`)}`),process.exit(1));let u=Math.floor((Date.now()-n)/1e3);d.text=`\u23F3 Deploying function... (${a.status}, ${u}s)`}catch(r){t.debug(`Status check failed: ${r.message}`)}await new Promise(r=>setTimeout(r,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(` ${k.default.cyan(`sinch functions status ${e}`)}`)}function bt(i){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")}[i]||k.default.gray(i)}async function Ro(i,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(i.docsPreference==="never")return;if(jo(i))n=!0;else{let o=await Ct.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"}]);o.docsChoice==="yes"?n=!0:o.docsChoice==="no"?n=!1:o.docsChoice==="always"?(n=!0,f.set("docsPreference","always",!0),await f.saveProjectConfig()):o.docsChoice==="never"&&(n=!1,f.set("docsPreference","never",!0),await f.saveProjectConfig())}}if(n)try{d.start("\u{1F4DD} Generating documentation...");let{generateDocsFromLocal:o,saveDocumentationToFile:s}=(wt(),_(on)),r=await o(),a=Se.default.basename(process.cwd());await s(r,"README.md",a),d.succeed("\u{1F4DD} Documentation updated in README.md")}catch(o){d.warn(`\u26A0\uFE0F Failed to generate documentation: ${o.message}`),t.warn("Continuing with deployment...")}}function jo(i){return i.docsPreference==="always"}async function To(i,e){if(e.private||i.accessPreference==="always-private")return"private";if(i.accessPreference==="always-public"||e.nonInteractive)return"public";let o=(await Ct.default.prompt([{type:"list",name:"accessChoice",message:"Deployment access level?",choices:[{name:"Public - Accessible from the internet",value:"public"},{name:"Private - Internal access only (Sinch services)",value:"private"},{name:"Always Public - Remember this choice",value:"always-public"},{name:"Always Private - Remember this choice",value:"always-private"}],default:"public"}])).accessChoice;return o==="always-public"?(f.set("accessPreference","always-public",!0),await f.saveProjectConfig(),"public"):o==="always-private"?(f.set("accessPreference","always-private",!0),await f.saveProjectConfig(),"private"):o}async function Do(i,e){d.start("Building function locally...");try{await new Promise((s,r)=>{let a=(0,Ue.spawn)("dotnet",["build",e,"-c","Release"],{cwd:i,stdio:"pipe",shell:!0}),u="",c="";a.stdout?.on("data",l=>{c+=l}),a.stderr?.on("data",l=>{u+=l}),a.on("close",l=>{l!==0?r(new Error(`Build failed:
52
- ${u||c}`)):s()})}),d.succeed("Build successful")}catch(s){throw d.fail("Build failed"),s}d.start("Starting function for validation...");let n=null,o="";try{if(n=(0,Ue.spawn)("dotnet",["run","--project",e,"--no-build","-c","Release"],{cwd:i,stdio:"pipe",shell:!0}),n.stdout?.on("data",r=>{o+=r.toString()}),n.stderr?.on("data",r=>{o+=r.toString()}),await Oo("http://localhost:3000/health",3e4))d.succeed("Function started and health check passed");else throw d.fail("Function failed to start within timeout"),o&&console.error(`
48
+ `,e+=`*Documentation generated on ${new Date(o.generatedAt).toLocaleString()} using Sinch AI*
49
+ `),e}async function Rt(o,e){let n=he.resolve(e);await Ue.writeFile(n,o,"utf8")}function Sn(o){switch(he.extname(o).toLowerCase()){case".js":case".ts":return"node";case".py":return"python";case".cs":return"csharp";default:return"node"}}var Ue,he,Ot=re(()=>{"use strict";Ue=m(require("fs-extra")),he=m(require("path"));K();D()});var Rn=F((hr,jn)=>{"use strict";var oe=m(require("fs-extra")),Ae=m(require("path")),k=m(require("chalk")),kn=require("commander");K();D();_();T();yn();wn();var Pn=m(require("adm-zip")),In=m(require("os")),Dt=m(require("inquirer")),ze=require("child_process"),An=m(require("keytar")),En=new kn.Command("deploy");En.description("Deploy function to production").option("-n, --name <name>","Function name (default: current directory)").option("--no-wait","Don't wait for deployment to complete").option("--non-interactive","Use default values without prompting (auto-generates docs)").option("--no-docs","no doc generation").option("--private","Deploy to private namespace (internal access only, not publicly accessible)").action(async o=>{try{if(await f.load(),!f.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=f.getProjectConfig(),n=o.name||e.name,i=e.runtime;if(await $i(e,o),i==="csharp"){let u=await oe.default.readdir(process.cwd()).then(C=>C.filter(w=>w.endsWith(".csproj")));if(u.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");let h=u[0];await Ii(process.cwd(),h)}l.start("\u{1F4E6} Packaging function...");let s=await bi(n);l.succeed("\u{1F4E6} Function packaged"),l.start("\u{1F527} Preparing configuration...");let a=await Si(i,n);l.succeed("\u{1F527} Configuration prepared");let r=await Pi(e,o);l.start("\u{1F680} Submitting deployment...");let c=new j(f.getApiConfig()),d=await oe.default.readFile(s),p=await c.deployFunction(n,i,d,a,r);if(await oe.default.remove(s),l.succeed("\u{1F680} Deployment submitted"),f.set("functionId",p.id,!0),await f.saveProjectConfig(),t.newline(),t.info(`Function ID: ${k.default.cyan(p.id)}`),t.info(`Status: ${_t(p.status)}`),o.wait===!1){t.newline(),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${k.default.cyan(`sinch functions status ${p.id}`)}`);return}await vi(c,p.id)}catch(e){l.stop(),t.error(`Failed to deploy function: ${e.message}`),process.exit(1)}});async function bi(o){let e=new Pn.default,n=process.cwd(),i=Ae.default.join(In.default.tmpdir(),`${o}-${Date.now()}.zip`),s=["node_modules","bin","obj",".git",".DS_Store","*.zip",".env",".env.local","npm-debug.log*",".sinch-tmp","examples","claude.md","readme.md",".vs",".vscode",".idea",".cursor","*.user","*.suo"];async function a(r,c=""){let d=await oe.default.readdir(r);for(let p of d){let u=Ae.default.join(r,p),h=Ae.default.join(c,p).replace(/\\/g,"/");if(s.some(w=>p.match(new RegExp(w.replace("*",".*")))))continue;if((await oe.default.stat(u)).isDirectory())await a(u,h);else{let w=await oe.default.readFile(u);e.addFile(h,w)}}}return await a(n),e.writeZip(i),i}async function Si(o,e){let n={},i=null;try{i=await f.getCredentials()}catch(s){t.debug("Could not load credentials from secure storage: "+s.message)}if(o==="csharp"){let s=Ae.default.join(process.cwd(),"appsettings.json");if(await oe.default.pathExists(s))try{let a=await oe.default.readJson(s);for(let r of Object.keys(a)){if(r==="Logging"||r==="AllowedHosts")continue;let c=a[r];if(c===""||c===null||c===void 0){let d="",p=!1;try{let h=(0,ze.execSync)("dotnet user-secrets list",{cwd:process.cwd(),encoding:"utf8",stdio:["pipe","pipe","pipe"]}).trim().split(`
50
+ `);for(let C of h){let w=C.match(/^([^=]+)\s*=\s*(.+)$/);if(w&&w[1]&&w[2]&&w[1].trim()===r){d=w[2].trim(),p=!0,t.debug(`Found ${r} in dotnet user-secrets`);break}}}catch{}!d&&i&&(r==="PROJECT_ID"&&i.projectId?d=i.projectId:r==="PROJECT_ID_API_KEY"&&i.keyId?d=i.keyId:r==="PROJECT_ID_API_SECRET"&&i.keySecret?(d=i.keySecret,p=!0):r==="VOICE_APPLICATION_KEY"&&i.applicationKey?d=i.applicationKey:r==="VOICE_APPLICATION_SECRET"&&i.applicationSecret&&(d=i.applicationSecret,p=!0)),d&&(n[r]={Value:d,Secret:p})}else n[r]={Value:String(c),Secret:!1}}}catch(a){t.debug("Could not read appsettings.json: "+a.message)}}else{let s=Ae.default.join(process.cwd(),".env");if(await oe.default.pathExists(s))try{let a=await oe.default.readFile(s,"utf8"),r={};a.split(`
51
+ `).forEach(d=>{if(d.trim()&&!d.trim().startsWith("#")){let[p,...u]=d.split("=");p&&(r[p.trim()]=u.join("=").trim())}});let c=["PORT","NODE_ENV","SINCH_TUNNEL"];for(let[d,p]of Object.entries(r))if(!c.includes(d))if(p===""||p===null||p===void 0){let u="",h=!1;if(i&&(d==="PROJECT_ID"&&i.projectId?u=i.projectId:d==="PROJECT_ID_API_KEY"&&i.keyId?u=i.keyId:d==="PROJECT_ID_API_SECRET"&&i.keySecret?(u=i.keySecret,h=!0):d==="VOICE_APPLICATION_KEY"&&i.applicationKey?u=i.applicationKey:d==="VOICE_APPLICATION_SECRET"&&i.applicationSecret&&(u=i.applicationSecret,h=!0)),!u)try{let C="sinch-functions-cli",w=`${e}-${d}`;u=await An.default.getPassword(C,w)||"",u&&(h=!0,t.debug(`Loaded custom secret ${d} from keychain`))}catch(C){t.debug(`Could not load ${d} from keychain: ${C.message}`)}u&&(n[d]={Value:u,Secret:h})}else n[d]={Value:p,Secret:!1}}catch(a){t.debug("Could not read .env file: "+a.message)}}return n}async function vi(o,e){let i=Date.now(),s=!1,a;return t.newline(),l.start("\u23F3 Connecting to deployment stream..."),new Promise((r,c)=>{let d,p;o.streamDeployment(e,u=>{let h=Math.floor((Date.now()-i)/1e3);switch(u.type){case"connected":l.text="\u23F3 Deployment stream connected, waiting for updates...";break;case"status":let C=u.data.data.message;l.text=`\u23F3 ${C} (${h}s)`;break;case"progress":let w=u.data.data.message,v=u.data.data.percentComplete;v?l.text=`\u23F3 ${w} (${v}%, ${h}s)`:l.text=`\u23F3 ${w} (${h}s)`;break;case"completed":s=!0,a=u.data.data.url,l.succeed("\u2705 Function deployed successfully"),o.getFunction(e).then(async Z=>{if(t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${k.default.cyan(Z.name)}`),t.info(` Status: ${_t("Running")}`),t.info(` URL: ${k.default.blue(a)}`),a){let I=await pt(),b=await Et();if(I.isConversation){t.newline(),t.info("\u{1F4AC} Conversation Integration:");try{l.start("Updating Sinch Conversation webhook..."),await At(a),l.succeed("Conversation webhook updated automatically"),t.info(` Webhook URL set to: ${k.default.cyan(a+"/conversation")}`)}catch(S){l.fail("Failed to update Conversation webhook");let y=S.response?.data?JSON.stringify(S.response.data):S.message;t.warn(` Error: ${y}`)}}if(b){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{l.start("Updating Sinch Voice callback URL..."),await It(a),l.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${k.default.cyan(a)}`)}catch(S){l.fail("Failed to update callback URL automatically"),t.warn(` Error: ${S.message}`),t.info(` Manual setup: ${k.default.cyan(`sinch voice callback-url ${a}`)}`)}}t.info(` Test function: ${k.default.cyan(`curl ${a}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${k.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${k.default.cyan(`sinch functions status ${e}`)}`),d&&d(),p&&clearTimeout(p),r()}).catch(Z=>{t.error(`Failed to get function details: ${Z.message}`),d&&d(),p&&clearTimeout(p),r()});break;case"failed":s=!0;let U=u.data.data.errorMessage;l.fail("\u274C Deployment failed"),t.newline(),t.error("Deployment failed:"),U&&t.error(` ${U}`),t.newline(),t.info("\u{1F4A1} Troubleshooting:"),t.info(` \u2022 Check logs: ${k.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${k.default.cyan(`sinch functions status ${e}`)}`),d&&d(),p&&clearTimeout(p),process.exit(1);break}},u=>{t.debug("SSE stream error, falling back to polling:",u),l.text="\u23F3 Deployment stream unavailable, checking status...",d&&d(),$n(o,e,i,3e5).then(r).catch(c)}).then(u=>{t.debug("SSE stream setup successful, cleanup function received"),d=u,p=setTimeout(()=>{s||(l.fail("\u23F0 Deployment timeout"),t.newline(),t.warn("Deployment is taking longer than expected"),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${k.default.cyan(`sinch functions status ${e}`)}`),d&&d(),r())},3e5)}).catch(u=>{t.debug(`Failed to set up SSE stream, falling back to polling: ${u.message}`),$n(o,e,i,3e5).then(r).catch(c)})})}async function $n(o,e,n,i){for(;Date.now()-n<i;){try{let r=(await o.getFunctionStatus(e)).function;if(r.status==="Running"){if(l.succeed("\u2705 Function deployed successfully"),t.newline(),t.info("\u{1F389} Deployment Complete!"),t.info(` Function: ${k.default.cyan(r.name)}`),t.info(` Status: ${_t(r.status)}`),t.info(` URL: ${k.default.blue(r.containerAppUrl)}`),r.containerAppUrl){let d=await pt(),p=await Et();if(d.isConversation){t.newline(),t.info("\u{1F4AC} Conversation Integration:");try{l.start("Updating Sinch Conversation webhook..."),await At(r.containerAppUrl),l.succeed("Conversation webhook updated automatically"),t.info(` Webhook URL set to: ${k.default.cyan(r.containerAppUrl+"/conversation")}`)}catch(u){l.fail("Failed to update Conversation webhook");let h=u.response?.data?JSON.stringify(u.response.data):u.message;t.warn(` Error: ${h}`)}}if(p){t.newline(),t.info("\u{1F4DE} Voice Integration:");try{l.start("Updating Sinch Voice callback URL..."),await It(r.containerAppUrl),l.succeed("Voice callback URL updated automatically"),t.info(` Callback URL set to: ${k.default.cyan(r.containerAppUrl)}`)}catch(u){l.fail("Failed to update callback URL automatically"),t.warn(` Error: ${u.message}`),t.info(` Manual setup: ${k.default.cyan(`sinch voice callback-url ${r.containerAppUrl}`)}`)}}t.info(` Test function: ${k.default.cyan(`curl ${r.containerAppUrl}`)}`)}t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 View logs: ${k.default.cyan(`sinch functions logs ${e} --follow`)}`),t.info(` \u2022 Check status: ${k.default.cyan(`sinch functions status ${e}`)}`);return}r.status==="Failed"&&(l.fail("\u274C Deployment failed"),t.newline(),t.error("Deployment failed:"),r.errorMessage&&t.error(` ${r.errorMessage}`),t.newline(),t.info("\u{1F4A1} Troubleshooting:"),t.info(` \u2022 Check logs: ${k.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Check status: ${k.default.cyan(`sinch functions status ${e}`)}`),process.exit(1));let c=Math.floor((Date.now()-n)/1e3);l.text=`\u23F3 Deploying function... (${r.status}, ${c}s)`}catch(a){t.debug(`Status check failed: ${a.message}`)}await new Promise(a=>setTimeout(a,3e3))}l.fail("\u23F0 Deployment timeout"),t.newline(),t.warn("Deployment is taking longer than expected"),t.info("\u{1F4A1} Check deployment progress with:"),t.info(` ${k.default.cyan(`sinch functions status ${e}`)}`)}function _t(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 $i(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(ki(o))n=!0;else{let i=await Dt.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,f.set("docsPreference","always",!0),await f.saveProjectConfig()):i.docsChoice==="never"&&(n=!1,f.set("docsPreference","never",!0),await f.saveProjectConfig())}}if(n)try{l.start("\u{1F4DD} Generating documentation...");let{generateDocsFromLocal:i,saveDocumentationToFile:s}=(Ot(),M(vn)),a=await i(),r=Ae.default.basename(process.cwd());await s(a,"README.md",r),l.succeed("\u{1F4DD} Documentation updated in README.md")}catch(i){l.warn(`\u26A0\uFE0F Failed to generate documentation: ${i.message}`),t.warn("Continuing with deployment...")}}function ki(o){return o.docsPreference==="always"}async function Pi(o,e){if(e.private||o.accessPreference==="always-private")return"private";if(o.accessPreference==="always-public"||e.nonInteractive)return"public";let i=(await Dt.default.prompt([{type:"list",name:"accessChoice",message:"Deployment access level?",choices:[{name:"Public - Accessible from the internet",value:"public"},{name:"Private - Internal access only (Sinch services)",value:"private"},{name:"Always Public - Remember this choice",value:"always-public"},{name:"Always Private - Remember this choice",value:"always-private"}],default:"public"}])).accessChoice;return i==="always-public"?(f.set("accessPreference","always-public",!0),await f.saveProjectConfig(),"public"):i==="always-private"?(f.set("accessPreference","always-private",!0),await f.saveProjectConfig(),"private"):i}async function Ii(o,e){l.start("Building function locally...");try{await new Promise((s,a)=>{let r=(0,ze.spawn)("dotnet",["build",e,"-c","Release"],{cwd:o,stdio:"pipe",shell:!0}),c="",d="";r.stdout?.on("data",p=>{d+=p}),r.stderr?.on("data",p=>{c+=p}),r.on("close",p=>{p!==0?a(new Error(`Build failed:
52
+ ${c||d}`)):s()})}),l.succeed("Build successful")}catch(s){throw l.fail("Build failed"),s}l.start("Starting function for validation...");let n=null,i="";try{if(n=(0,ze.spawn)("dotnet",["run","--project",e,"--no-build","-c","Release"],{cwd:o,stdio:"pipe",shell:!0}),n.stdout?.on("data",a=>{i+=a.toString()}),n.stderr?.on("data",a=>{i+=a.toString()}),await Ai("http://localhost:3000/health",3e4))l.succeed("Function started and health check passed");else throw l.fail("Function failed to start within timeout"),i&&console.error(`
53
53
  Process output:
54
- `+o),new Error("Function validation failed: could not start function")}catch(s){throw d.fail("Validation failed"),o&&console.error(`
54
+ `+i),new Error("Function validation failed: could not start function")}catch(s){throw l.fail("Validation failed"),i&&console.error(`
55
55
  Process output:
56
- `+o),s}finally{if(n&&n.pid){try{process.kill(n.pid)}catch{}await new Promise(s=>setTimeout(s,1e3))}}}async function Oo(i,e){let n=Date.now();for(;Date.now()-n<e;){try{if((await fetch(i)).ok)return!0}catch{}await new Promise(o=>setTimeout(o,500))}return!1}dn.exports=un});var yn=K((ys,hn)=>{"use strict";var T=h(require("fs-extra")),oe=h(require("path")),Be=h(require("chalk")),St=require("child_process"),fn=require("commander"),gn=h(require("inquirer"));j();B();L();var mn=new fn.Command("dev");mn.description("Start local development server").option("-p, --port <port>","Port to run on","3000").option("-d, --debug","Enable debugging with --inspect").option("--tunnel","Force tunnel creation").option("--no-tunnel",'Disable tunnel and reset "always" preference').action(async i=>{try{if(await f.load(),!f.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=f.getProjectConfig();if(!e)throw new Error("No project configuration found");let n=e.runtime||"node",o;if(n==="csharp"){let s=await T.default.readdir(process.cwd()).then(r=>r.filter(a=>a.endsWith(".csproj")));if(s.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");o=s[0],t.debug(`Using project file: ${o}`)}else{let s=oe.default.join(process.cwd(),"node_modules",".bin","sinch-runtime");if(!await T.default.pathExists(s))throw new Error("@sinch/functions-runtime not found. Run npm install first.")}t.title(`Starting ${e.name} (${e.runtime})`),t.info(`Port: ${i.port}`),t.newline(),await _o(i,e,o)}catch(e){d.stop(),t.error(`Failed to start development server: ${e.message}`),process.exit(1)}});async function Fo(i,e){if(e==="node"){let n=oe.default.join(process.cwd(),".env");if(await T.default.pathExists(n)){let o=await T.default.readFile(n,"utf-8"),s=`SINCH_TUNNEL=${i}`;o.includes("SINCH_TUNNEL=")?o=o.replace(/SINCH_TUNNEL=(true|false)/g,s):o+=`
56
+ `+i),s}finally{if(n&&n.pid){try{process.kill(n.pid)}catch{}await new Promise(s=>setTimeout(s,1e3))}}}async function Ai(o,e){let n=Date.now();for(;Date.now()-n<e;){try{if((await fetch(o)).ok)return!0}catch{}await new Promise(i=>setTimeout(i,500))}return!1}jn.exports=En});var Nn=F((Sr,Tn)=>{"use strict";var x=m(require("fs-extra")),ce=m(require("path")),Qe=m(require("chalk")),Tt=require("child_process"),On=require("commander"),Dn=m(require("inquirer"));D();_();T();var _n=new On.Command("dev");_n.description("Start local development server").option("-p, --port <port>","Port to run on","3000").option("-d, --debug","Enable debugging with --inspect").option("--tunnel","Force tunnel creation").option("--no-tunnel",'Disable tunnel and reset "always" preference').action(async o=>{try{if(await f.load(),!f.isInProject())throw new Error('Not in a Sinch Functions project directory. Run "sinch functions init" first.');let e=f.getProjectConfig();if(!e)throw new Error("No project configuration found");let n=e.runtime||"node",i;if(n==="csharp"){let s=await x.default.readdir(process.cwd()).then(a=>a.filter(r=>r.endsWith(".csproj")));if(s.length===0)throw new Error("No .csproj file found. Make sure you're in a valid C# function directory.");i=s[0],t.debug(`Using project file: ${i}`)}else{let s=ce.default.join(process.cwd(),"node_modules",".bin","sinch-runtime");if(!await x.default.pathExists(s))throw new Error("@sinch/functions-runtime not found. Run npm install first.")}t.title(`Starting ${e.name} (${e.runtime})`),t.info(`Port: ${o.port}`),t.newline(),await ji(o,e,i)}catch(e){l.stop(),t.error(`Failed to start development server: ${e.message}`),process.exit(1)}});async function Ei(o,e){if(e==="node"){let n=ce.default.join(process.cwd(),".env");if(await x.default.pathExists(n)){let i=await x.default.readFile(n,"utf-8"),s=`SINCH_TUNNEL=${o}`;i.includes("SINCH_TUNNEL=")?i=i.replace(/SINCH_TUNNEL=(true|false)/g,s):i+=`
57
57
  ${s}
58
- `,await T.default.writeFile(n,o,"utf-8"),t.debug(`Updated .env: SINCH_TUNNEL=${i}`)}}else if(e==="csharp"){let n=oe.default.join(process.cwd(),"appsettings.Development.json");if(await T.default.pathExists(n)){let o=await T.default.readJson(n);o.SinchTunnel=i,await T.default.writeJson(n,o,{spaces:2}),t.debug(`Updated appsettings.Development.json: SinchTunnel=${i}`)}}}async function _o(i,e,n){let o=e.runtime||"node",s=!1;if(i.tunnel===!0)s=!0;else if(i.tunnel===!1)s=!1,e.tunnel?.preference==="always"&&(f.set("tunnel",{...e.tunnel,preference:"no"},!0),await f.saveProjectConfig());else if(e.tunnel?.preference==="never")s=!1;else if(Uo(e))s=!0;else{let{tunnelChoice:l}=await gn.default.prompt([{type:"list",name:"tunnelChoice",message:"Enable Sinch tunnel for external access?",choices:[{name:"Yes - Enable tunnel this time",value:"yes"},{name:"No - Local only this time",value:"no"},{name:"Always - Enable tunnel and remember preference",value:"always"},{name:"Never - Don't enable tunnel and remember preference",value:"never"}],default:"no"}]);l==="yes"?s=!0:l==="no"?s=!1:l==="always"?(s=!0,f.set("tunnel",{...e.tunnel,preference:"always"},!0),await f.saveProjectConfig()):l==="never"&&(s=!1,f.set("tunnel",{...e.tunnel,preference:"never"},!0),await f.saveProjectConfig())}await Fo(s,o);let r={...process.env,PORT:i.port,NODE_ENV:"development",SINCH_FUNCTIONS_LOCAL:"true",SINCH_TUNNEL:s?"true":"false"};e.variables&&Object.entries(e.variables).forEach(([l,p])=>{r[l]=p});try{let l=await f.getApplicationCredentials(e.voiceAppKey);l?(r.SINCH_APPLICATION_KEY=l.applicationKey,r.SINCH_APPLICATION_SECRET=l.applicationSecret,t.debug("\u2705 Injected application credentials for voice operations")):t.debug("\u26A0\uFE0F No application credentials found - voice features may not work")}catch(l){t.debug(`\u26A0\uFE0F Could not load application credentials: ${l.message}`)}t.info("\u{1F680} Starting local server...");let a=null,u=!1;function c(){if(a&&a.kill(),o==="csharp"){let l=["watch","run","--no-launch-profile"];n&&l.push("--project",n),i.port&&l.push("--urls",`http://localhost:${i.port}`),r.ASPNETCORE_ENVIRONMENT="Development",r.ASPNETCORE_URLS=`http://localhost:${i.port}`,a=(0,St.spawn)("dotnet",l,{env:r,stdio:"inherit",cwd:process.cwd()})}else a=(0,St.spawn)("npm",["run","dev"],{env:r,stdio:"inherit",cwd:process.cwd(),shell:!0});a.on("spawn",async()=>{if(!u){u=!0,t.newline(),t.success(`\u2705 Server running on http://localhost:${i.port}`),i.debug&&(t.newline(),o==="csharp"?Bo():Lo()),t.newline(),t.info("\u{1F4A1} Development commands:"),t.info(` \u2022 Test function: ${Be.default.cyan(`curl http://localhost:${i.port}`)}`),t.info(` \u2022 View in browser: ${Be.default.cyan(`http://localhost:${i.port}`)}`),t.info(` \u2022 Stop server: ${Be.default.gray("Ctrl+C")}`);let l=o==="csharp"?"dotnet watch":"nodemon";t.info(` \u2022 File watching: ${Be.default.green(`enabled (via ${l})`)}`)}}),a.on("error",l=>{t.error(`Server error: ${l.message}`)}),a.on("exit",(l,p)=>{p!=="SIGTERM"&&p!=="SIGKILL"&&t.error(`Server exited with code ${l}`)})}c(),process.on("SIGINT",()=>{t.newline(),t.info("\u{1F534} Stopping development server..."),a&&a.kill("SIGTERM"),process.exit(0)}),await new Promise(()=>{})}async function Lo(){try{let i=await De("code",".vscode"),e=await De("cursor",".cursor"),n=await De("webstorm",".idea");if(i||e){let o=i?"VS Code":"Cursor",s=".vscode";if(t.info(`\u{1F41B} ${o} detected! Debug setup:`),await No(s))t.info(" 1. \u2705 Created .vscode/launch.json for you");else{let a=oe.default.join(process.cwd(),s,"launch.json");await T.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 De(i,e){try{if(i==="code"&&xo())return!0;let{spawn:n}=require("child_process"),o=await new Promise(r=>{let a=n(i,["--version"],{stdio:"pipe"});a.on("close",u=>r(u===0)),a.on("error",()=>r(!1))}),s=e?await T.default.pathExists(e):!1;return o||s}catch{return!1}}function xo(){return process.env.TERM_PROGRAM==="vscode"||!!process.env.VSCODE_IPC_HOOK||!!process.env.VSCODE_PID}async function No(i=".vscode"){try{let e=oe.default.join(process.cwd(),i),n=oe.default.join(e,"launch.json");if(await T.default.pathExists(n))return!1;await T.default.ensureDir(e);let o={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 T.default.writeJson(n,o,{spaces:2}),!!await T.default.pathExists(n)}catch{return!1}}function Uo(i){return i.tunnel?i.tunnel.preference==="always":!1}async function Bo(){try{let i=await De("code",".vscode"),e=await De("devenv"),n=await De("rider",".idea");i?(t.info("\u{1F41B} VS Code detected! Debug setup:"),await Ko(".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 Ko(i=".vscode"){try{let e=oe.default.join(process.cwd(),i),n=oe.default.join(e,"launch.json");if(await T.default.pathExists(n))return!1;await T.default.ensureDir(e);let o={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 T.default.writeJson(n,o,{spaces:2});let s=oe.default.join(e,"tasks.json");if(!await T.default.pathExists(s)){let r={version:"2.0.0",tasks:[{label:"build",command:"dotnet",type:"process",args:["build","${workspaceFolder}/Function.csproj","/property:GenerateFullPaths=true","/consoleloggerparameters:NoSummary"],problemMatcher:"$msCompile"}]};await T.default.writeJson(s,r,{spaces:2})}return await T.default.pathExists(n)}catch{return!1}}hn.exports=mn});var vn=K((vs,Sn)=>{"use strict";var J=h(require("chalk")),wn=require("commander");U();j();B();L();var Cn=new wn.Command("status");Cn.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(i,e)=>{try{await f.load();let n=new A(f.getApiConfig()),o=i;if(!o){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");if(o=f.getProjectConfig()?.functionId,!o)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}e.follow?await qo(n,o):await Vo(n,o,e)}catch(n){d.stop(),t.error(`Failed to get function status: ${n.message}`),process.exit(1)}});async function Vo(i,e,n){d.start("\u{1F4E1} Loading function status...");try{let o=await i.getFunction(e),s=await i.getFunctionStatus(e);if(d.stop(),n.json){console.log(JSON.stringify({function:o,deployment:s},null,2));return}let r=o,a=s.status,u=s.error;t.newline(),t.title(`Function Status: ${r.name}`),t.newline(),t.info("\u{1F4CB} Function Details:"),t.info(` ID: ${J.default.gray(r.id)}`),t.info(` Name: ${J.default.cyan(r.name)}`),t.info(` Runtime: ${J.default.yellow(r.runtime)}`),t.info(` Deployment Status: ${bn(a)}`),r.created&&t.info(` Created: ${new Date(r.created).toLocaleString()}`),r.updated&&t.info(` Updated: ${new Date(r.updated).toLocaleString()}`),r.url&&t.info(` URL: ${J.default.blue(r.url)}`),a==="Failed"&&u&&(t.newline(),t.error("Deployment Error:"),t.error(` ${u}`)),t.newline(),t.info("\u{1F4A1} Commands:"),t.info(` \u2022 View logs: ${J.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Redeploy: ${J.default.cyan("sinch functions deploy")}`),t.info(` \u2022 Delete: ${J.default.cyan(`sinch functions delete ${e}`)}`)}catch(o){throw d.stop(),o}}async function qo(i,e){t.info("\u{1F440} Watching deployment status (press Ctrl+C to stop)..."),t.newline();let n=null,o=setInterval(async()=>{try{let s=await i.getFunctionStatus(e),r=s.status;if(r!==n){let a=new Date().toLocaleTimeString();if(t.info(`[${a}] Status: ${bn(r)}`),n=r,r==="Running"){t.success("Function deployment is now running!");try{let u=await i.getFunction(e);u.url&&t.info(`URL: ${J.default.blue(u.url)}`)}catch{}}else r==="Failed"&&(t.error("Function deployment failed!"),s.error&&t.error(`Error: ${s.error}`),clearInterval(o))}}catch(s){t.error(`Error checking status: ${s.message}`)}},3e3);process.on("SIGINT",()=>{clearInterval(o),t.newline(),t.info("Stopped watching function status"),process.exit(0)})}function bn(i){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")}[i]||J.default.gray(i)}Sn.exports=Cn});var Tn=K((Is,jn)=>{"use strict";var ve=h(require("chalk")),Pn=require("commander");U();j();B();L();var vt=require("child_process"),Ke=h(require("fs")),Ve=h(require("os")),qe=h(require("path")),$t=new Pn.Command("logs");$t.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(i,e)=>{try{await f.load();let n=new A(f.getApiConfig()),o=i;if(!o){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let r=f.getProjectConfig();if(!r)throw new Error("No project configuration found");if(o=r.functionId,!o)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 s=await n.getFunction(o);d.stop(),t.info(`\u{1F4CB} Logs for function: ${ve.default.cyan(s.name)} (${Mo(s.status)})`),t.newline(),e.follow?await En(n,o,s.name,e):await ti(n,o,e)}catch(n){d.stop(),t.error(`Failed to get logs: ${n.message}`),process.exit(1)}});$t.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(i,e)=>{try{await f.load();let n=new A(f.getApiConfig()),o=i;if(!o){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let r=f.getProjectConfig();if(!r)throw new Error("No project configuration found");if(o=r.functionId,!o)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 s=await Jo(n,o);d.stop(),await En(n,o,s.name,{...e,follow:!0})}catch(n){d.stop(),t.error(`Failed to stream logs: ${n.message}`),process.exit(1)}});async function Jo(i,e){return await i.getFunction(e)}async function En(i,e,n,o){let s=i.baseUrl.replace(/\/+$/,""),r=i.projectId,a=`${s}/v1/projects/${r}/functions/${e}/logs/stream`,u=i.credentials,c=[],l=An(c,"STREAMING",n),p={Accept:"text/event-stream","Cache-Control":"no-cache"};if(u)try{let C=await u.retrieve();if(C&&C.keyId&&C.keySecret){let w=Buffer.from(`${C.keyId}:${C.keySecret}`).toString("base64");p.Authorization=`Basic ${w}`}}catch(C){t.debug("Failed to add authentication:",C)}let m=new AbortController;try{let C=await fetch(a,{method:"GET",headers:p,signal:m.signal});if(!C.ok)throw new Error(`SSE connection failed: ${C.status} ${C.statusText}`);if(!C.body)throw new Error("Response body is null");$n(l.statusBar,"CONNECTED",n),l.screen.render();let w=C.body.getReader(),v=new TextDecoder,O="";(async()=>{try{for(;;){let{done:E,value:b}=await w.read();if(E)break;O+=v.decode(b,{stream:!0});let S=O.split(`
59
- `);O=S.pop()||"";for(let y of S)if(!y.startsWith("event:")&&y.startsWith("data:")){let $=y.substring(5).trim();if($)try{let R=JSON.parse($);R.type==="request"&&R.request&&(c.push(R.request),In(l.table,R.request,c),l.table.focus(),l.screen.render())}catch{}}}}catch(E){E.name!=="AbortError"&&($n(l.statusBar,"RECONNECTING",n),l.screen.render())}})(),l.screen.key(["q","C-c"],()=>{m.abort(),process.exit(0)}),await new Promise(()=>{})}catch(C){m.abort(),t.error(`\u274C Streaming failed: ${C.message}`),process.exit(1)}}function Mo(i){return{Running:ve.default.green("\u2705 Running"),Failed:ve.default.red("\u274C Failed"),Pending:ve.default.yellow("\u23F3 Pending"),Building:ve.default.blue("\u{1F528} Building")}[i]||ve.default.gray(i)}var $e=[];function In(i,e,n){let o=new Date(e.startTime),s=o.getFullYear()+"-"+String(o.getMonth()+1).padStart(2,"0")+"-"+String(o.getDate()).padStart(2,"0")+" "+String(o.getHours()).padStart(2,"0")+":"+String(o.getMinutes()).padStart(2,"0")+":"+String(o.getSeconds()).padStart(2,"0"),r=ei(e),a=`${e.executionTimeMs}ms`,u=e.statusCode.toString(),c=process.stdout.columns||120,p=Math.max(30,c-35),m=e.url.length>p?e.url.substring(0,p-2)+"..":e.url;$e.push([s,r,a,u,m]),$e.length>100&&($e=$e.slice(-100),n&&n.length>100&&n.splice(0,n.length-100));let C=[["Time","Callback","Duration","Status","Path"],...$e];i.setData(C)}function Wo(i,e,n,o,s){try{let r=require("blessed");t.debug(`Showing request details for ${i.httpMethod} ${i.url}`);let a=r.box({parent:e,top:0,left:0,width:"100%",height:"100%",border:{type:"line"},style:{border:{fg:"cyan"},bg:"black",fg:"white"},scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,label:" Request Details "}),u=r.box({parent:a,top:1,left:2,width:"100%-4",height:1,content:"{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J/1] JSON [C/2] cURL{/}",tags:!0,style:{bg:"blue",fg:"white"}});r.box({parent:a,top:2,left:2,width:"100%-4",height:1,content:`{bold}{cyan-fg}${i.httpMethod}{/} {blue-fg}${i.url}{/} - {${Zo(i.statusCode)}}${i.statusCode}{/} - {yellow-fg}${i.executionTimeMs}ms{/} - {magenta-fg}${i.memoryUsedMB||0}MB{/}`,tags:!0,style:{bg:"black"}});let c=r.box({parent:a,top:4,left:2,width:"100%-4",height:"100%-5",scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,content:Ho(i)});c.focus(),e.render();let l=!0,p=()=>{l&&(l=!1,a.destroy(),n.focus(),e.render())};e.key(["escape","q"],()=>{l&&p()}),e.key(["up","k"],()=>{l&&(c.scroll(-1),e.render())}),e.key(["down","j"],()=>{l&&(c.scroll(1),e.render())}),e.on("keypress",(m,C)=>{l&&t.debug(`Key pressed: ch="${m}" key=${JSON.stringify(C)}`)}),e.key(["J","j"],()=>{l&&(t.debug("J/j key pressed - attempting JSON copy"),u.setContent("{black-bg}{yellow-fg} J KEY PRESSED - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let m=JSON.stringify(i,null,2);t.debug(`JSON content length: ${m.length}`),t.debug("Attempting native clipboard copy"),et(m).then(()=>{u.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded"),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(C=>{t.debug(`Native clipboard failed: ${C.message}`);let w=qe.default.join(Ve.default.tmpdir(),`sinch-request-${Date.now()}.json`);Ke.default.writeFileSync(w,m),u.setContent(`{yellow-fg}\u2713 JSON saved to: ${w}{/}`),t.debug(`Saved to temp file: ${w}`),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){t.debug(`JSON copy error: ${m.message}`),u.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["C","c"],()=>{l&&(t.debug("C/c key pressed - attempting cURL copy"),u.setContent("{black-bg}{yellow-fg} C KEY PRESSED - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let m=kn(i);t.debug("Attempting native clipboard copy for cURL"),et(m).then(()=>{u.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded for cURL"),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(C=>{t.debug(`Native clipboard failed for cURL: ${C.message}`);let w=qe.default.join(Ve.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);Ke.default.writeFileSync(w,m),u.setContent(`{yellow-fg}\u2713 cURL saved to: ${w}{/}`),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){t.debug(`cURL copy error: ${m.message}`),u.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["1"],()=>{l&&(t.debug("1 key pressed - copying JSON (alternative binding)"),u.setContent("{black-bg}{yellow-fg} 1 KEY - COPYING JSON... {/}"),e.render(),setTimeout(()=>{try{let m=JSON.stringify(i,null,2);et(m).then(()=>{u.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(C=>{let w=qe.default.join(Ve.default.tmpdir(),`sinch-request-${Date.now()}.json`);Ke.default.writeFileSync(w,m),u.setContent(`{yellow-fg}\u2713 JSON saved to: ${w}{/}`),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){u.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["2"],()=>{l&&(t.debug("2 key pressed - copying cURL (alternative binding)"),u.setContent("{black-bg}{yellow-fg} 2 KEY - COPYING CURL... {/}"),e.render(),setTimeout(()=>{try{let m=kn(i);et(m).then(()=>{u.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(C=>{let w=qe.default.join(Ve.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);Ke.default.writeFileSync(w,m),u.setContent(`{yellow-fg}\u2713 cURL saved to: ${w}{/}`),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)})}catch(m){u.setContent(`{red-fg}\u2717 Copy failed: ${m.message}{/}`),e.render(),setTimeout(()=>{l&&(u.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))})}catch(r){t.debug(`Error in showBlessedZoomedRequest: ${r.message}`)}}function Ho(i){let e="";return e+=`
60
- `,e+=Go(i),e+=`
61
- `,e+=Yo(i),e+=`
62
- `,e+=zo(i),e}function Go(i){let e="",n=process.stdout.columns-6;e+="{bold}{green-fg}\u250C\u2500 REQUEST "+"\u2500".repeat(Math.max(0,n-10))+`\u2510{/}
63
- `;let o=Xo(i);if(o&&(e+=`{green-fg}\u2502{/} {bold}Call ID:{/} {cyan-fg}${o}{/}
64
- `),i.headers){e+=`{green-fg}\u2502{/} {bold}Headers:{/}
65
- `;try{let s=typeof i.headers=="string"?JSON.parse(i.headers):i.headers;Object.entries(s).forEach(([r,a])=>{let u=` ${r}: ${a}`;e+=ie(u,n-2,"{green-fg}\u2502{/} ")})}catch{e+=ie(` ${i.headers}`,n-2,"{green-fg}\u2502{/} ")}}if(i.requestBody){e+=`{green-fg}\u2502{/} {bold}Body:{/}
66
- `;try{let s=JSON.parse(i.requestBody);JSON.stringify(s,null,2).split(`
67
- `).forEach(a=>{e+=ie(a,n-2,"{green-fg}\u2502{/} ")})}catch{e+=ie(i.requestBody,n-2,"{green-fg}\u2502{/} ")}}return e+="{green-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
68
- `,e}function Yo(i){let e="",n=process.stdout.columns-6;if(e+="{bold}{blue-fg}\u250C\u2500 RESPONSE "+"\u2500".repeat(Math.max(0,n-11))+`\u2510{/}
69
- `,i.responseHeaders){e+=`{blue-fg}\u2502{/} {bold}Headers:{/}
70
- `;try{let o=typeof i.responseHeaders=="string"?JSON.parse(i.responseHeaders):i.responseHeaders;Object.entries(o).forEach(([s,r])=>{let a=` ${s}: ${r}`;e+=ie(a,n-2,"{blue-fg}\u2502{/} ")})}catch{e+=ie(` ${i.responseHeaders}`,n-2,"{blue-fg}\u2502{/} ")}}if(i.responseBody){e+=`{blue-fg}\u2502{/} {bold}Body:{/}
71
- `;try{let o=JSON.parse(i.responseBody);JSON.stringify(o,null,2).split(`
72
- `).forEach(r=>{e+=ie(r,n-2,"{blue-fg}\u2502{/} ")})}catch{e+=ie(i.responseBody,n-2,"{blue-fg}\u2502{/} ")}}return i.errorMessage&&(e+=`{blue-fg}\u2502{/} {bold}{red-fg}Error:{/}
73
- `,e+=ie(i.errorMessage,n-2,"{blue-fg}\u2502{/} ")),e+="{blue-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
74
- `,e}function zo(i){let e="",n=process.stdout.columns-6;return e+="{bold}{magenta-fg}\u250C\u2500 CONSOLE LOGS "+"\u2500".repeat(Math.max(0,n-15))+`\u2510{/}
75
- `,i.logs&&i.logs.length>0?i.logs.forEach((o,s)=>{let r=new Date(o.timestamp).toLocaleTimeString(),a=o.level.toUpperCase().padEnd(5),u=Qo(o.level),c=`${r} [${a}] ${o.message}`;e+=ie(c,n-2,"{magenta-fg}\u2502{/} ",u)}):e+=`{magenta-fg}\u2502{/} {gray-fg}No console logs for this request{/}
58
+ `,await x.default.writeFile(n,i,"utf-8"),t.debug(`Updated .env: SINCH_TUNNEL=${o}`)}}else if(e==="csharp"){let n=ce.default.join(process.cwd(),"appsettings.Development.json");if(await x.default.pathExists(n)){let i=await x.default.readJson(n);i.SinchTunnel=o,await x.default.writeJson(n,i,{spaces:2}),t.debug(`Updated appsettings.Development.json: SinchTunnel=${o}`)}}}async function ji(o,e,n){let i=e.runtime||"node",s=!1;if(o.tunnel===!0)s=!0;else if(o.tunnel===!1)s=!1,e.tunnel?.preference==="always"&&(f.set("tunnel",{...e.tunnel,preference:"no"},!0),await f.saveProjectConfig());else if(e.tunnel?.preference==="never")s=!1;else if(_i(e))s=!0;else{let{tunnelChoice:p}=await Dn.default.prompt([{type:"list",name:"tunnelChoice",message:"Enable Sinch tunnel for external access?",choices:[{name:"Yes - Enable tunnel this time",value:"yes"},{name:"No - Local only this time",value:"no"},{name:"Always - Enable tunnel and remember preference",value:"always"},{name:"Never - Don't enable tunnel and remember preference",value:"never"}],default:"no"}]);p==="yes"?s=!0:p==="no"?s=!1:p==="always"?(s=!0,f.set("tunnel",{...e.tunnel,preference:"always"},!0),await f.saveProjectConfig()):p==="never"&&(s=!1,f.set("tunnel",{...e.tunnel,preference:"never"},!0),await f.saveProjectConfig())}await Ei(s,i);let a={...process.env,PORT:o.port,NODE_ENV:"development",SINCH_FUNCTIONS_LOCAL:"true",SINCH_TUNNEL:s?"true":"false"};e.variables&&Object.entries(e.variables).forEach(([p,u])=>{a[p]=u});try{let p=await f.getApplicationCredentials(e.voiceAppKey);p?(a.SINCH_APPLICATION_KEY=p.applicationKey,a.SINCH_APPLICATION_SECRET=p.applicationSecret,t.debug("\u2705 Injected application credentials for voice operations")):t.debug("\u26A0\uFE0F No application credentials found - voice features may not work")}catch(p){t.debug(`\u26A0\uFE0F Could not load application credentials: ${p.message}`)}t.info("\u{1F680} Starting local server...");let r=null,c=!1;function d(){if(r&&r.kill(),i==="csharp"){let p=["watch","run","--no-launch-profile"];n&&p.push("--project",n),o.port&&p.push("--urls",`http://localhost:${o.port}`),a.ASPNETCORE_ENVIRONMENT="Development",a.ASPNETCORE_URLS=`http://localhost:${o.port}`,r=(0,Tt.spawn)("dotnet",p,{env:a,stdio:"inherit",cwd:process.cwd()})}else r=(0,Tt.spawn)("npm",["run","dev"],{env:a,stdio:"inherit",cwd:process.cwd(),shell:!0});r.on("spawn",async()=>{if(!c){c=!0,t.newline(),t.success(`\u2705 Server running on http://localhost:${o.port}`),o.debug&&(t.newline(),i==="csharp"?Ti():Ri()),t.newline(),t.info("\u{1F4A1} Development commands:"),t.info(` \u2022 Test function: ${Qe.default.cyan(`curl http://localhost:${o.port}`)}`),t.info(` \u2022 View in browser: ${Qe.default.cyan(`http://localhost:${o.port}`)}`),t.info(` \u2022 Stop server: ${Qe.default.gray("Ctrl+C")}`);let p=i==="csharp"?"dotnet watch":"nodemon";t.info(` \u2022 File watching: ${Qe.default.green(`enabled (via ${p})`)}`)}}),r.on("error",p=>{t.error(`Server error: ${p.message}`)}),r.on("exit",(p,u)=>{u!=="SIGTERM"&&u!=="SIGKILL"&&t.error(`Server exited with code ${p}`)})}d(),process.on("SIGINT",()=>{t.newline(),t.info("\u{1F534} Stopping development server..."),r&&r.kill("SIGTERM"),process.exit(0)}),await new Promise(()=>{})}async function Ri(){try{let o=await Me("code",".vscode"),e=await Me("cursor",".cursor"),n=await Me("webstorm",".idea");if(o||e){let i=o?"VS Code":"Cursor",s=".vscode";if(t.info(`\u{1F41B} ${i} detected! Debug setup:`),await Di(s))t.info(" 1. \u2705 Created .vscode/launch.json for you");else{let r=ce.default.join(process.cwd(),s,"launch.json");await x.default.pathExists(r)?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 Me(o,e){try{if(o==="code"&&Oi())return!0;let{spawn:n}=require("child_process"),i=await new Promise(a=>{let r=n(o,["--version"],{stdio:"pipe"});r.on("close",c=>a(c===0)),r.on("error",()=>a(!1))}),s=e?await x.default.pathExists(e):!1;return i||s}catch{return!1}}function Oi(){return process.env.TERM_PROGRAM==="vscode"||!!process.env.VSCODE_IPC_HOOK||!!process.env.VSCODE_PID}async function Di(o=".vscode"){try{let e=ce.default.join(process.cwd(),o),n=ce.default.join(e,"launch.json");if(await x.default.pathExists(n))return!1;await x.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 x.default.writeJson(n,i,{spaces:2}),!!await x.default.pathExists(n)}catch{return!1}}function _i(o){return o.tunnel?o.tunnel.preference==="always":!1}async function Ti(){try{let o=await Me("code",".vscode"),e=await Me("devenv"),n=await Me("rider",".idea");o?(t.info("\u{1F41B} VS Code detected! Debug setup:"),await Ni(".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 Ni(o=".vscode"){try{let e=ce.default.join(process.cwd(),o),n=ce.default.join(e,"launch.json");if(await x.default.pathExists(n))return!1;await x.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 x.default.writeJson(n,i,{spaces:2});let s=ce.default.join(e,"tasks.json");if(!await x.default.pathExists(s)){let a={version:"2.0.0",tasks:[{label:"build",command:"dotnet",type:"process",args:["build","${workspaceFolder}/Function.csproj","/property:GenerateFullPaths=true","/consoleloggerparameters:NoSummary"],problemMatcher:"$msCompile"}]};await x.default.writeJson(s,a,{spaces:2})}return await x.default.pathExists(n)}catch{return!1}}Tn.exports=_n});var Mn=F((Ir,Un)=>{"use strict";var H=m(require("chalk")),Fn=require("commander");K();D();_();T();var xn=new Fn.Command("status");xn.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 f.load();let n=new j(f.getApiConfig()),i=o;if(!i){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");if(i=f.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 xi(n,i):await Fi(n,i,e)}catch(n){l.stop(),t.error(`Failed to get function status: ${n.message}`),process.exit(1)}});async function Fi(o,e,n){l.start("\u{1F4E1} Loading function status...");try{let i=await o.getFunction(e),s=await o.getFunctionStatus(e);if(l.stop(),n.json){console.log(JSON.stringify({function:i,deployment:s},null,2));return}let a=i,r=s.status,c=s.error;t.newline(),t.title(`Function Status: ${a.name}`),t.newline(),t.info("\u{1F4CB} Function Details:"),t.info(` ID: ${H.default.gray(a.id)}`),t.info(` Name: ${H.default.cyan(a.name)}`),t.info(` Runtime: ${H.default.yellow(a.runtime)}`),t.info(` Deployment Status: ${Ln(r)}`),a.created&&t.info(` Created: ${new Date(a.created).toLocaleString()}`),a.updated&&t.info(` Updated: ${new Date(a.updated).toLocaleString()}`),a.url&&t.info(` URL: ${H.default.blue(a.url)}`),r==="Failed"&&c&&(t.newline(),t.error("Deployment Error:"),t.error(` ${c}`)),t.newline(),t.info("\u{1F4A1} Commands:"),t.info(` \u2022 View logs: ${H.default.cyan(`sinch functions logs ${e}`)}`),t.info(` \u2022 Redeploy: ${H.default.cyan("sinch functions deploy")}`),t.info(` \u2022 Delete: ${H.default.cyan(`sinch functions delete ${e}`)}`)}catch(i){throw l.stop(),i}}async function xi(o,e){t.info("\u{1F440} Watching deployment status (press Ctrl+C to stop)..."),t.newline();let n=null,i=setInterval(async()=>{try{let s=await o.getFunctionStatus(e),a=s.status;if(a!==n){let r=new Date().toLocaleTimeString();if(t.info(`[${r}] Status: ${Ln(a)}`),n=a,a==="Running"){t.success("Function deployment is now running!");try{let c=await o.getFunction(e);c.url&&t.info(`URL: ${H.default.blue(c.url)}`)}catch{}}else a==="Failed"&&(t.error("Function deployment failed!"),s.error&&t.error(`Error: ${s.error}`),clearInterval(i))}}catch(s){t.error(`Error checking status: ${s.message}`)}},3e3);process.on("SIGINT",()=>{clearInterval(i),t.newline(),t.info("Stopped watching function status"),process.exit(0)})}function Ln(o){return{Running:H.default.green("\u2705 Running"),Failed:H.default.red("\u274C Failed"),Pending:H.default.yellow("\u23F3 Pending"),Building:H.default.blue("\u{1F528} Building")}[o]||H.default.gray(o)}Un.exports=xn});var Yn=F((Or,Hn)=>{"use strict";var Ee=m(require("chalk")),Bn=require("commander");K();D();_();T();var Nt=require("child_process"),Ze=m(require("fs")),Xe=m(require("os")),et=m(require("path")),Ft=new Bn.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 f.load();let n=new j(f.getApiConfig()),i=o;if(!i){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let a=f.getProjectConfig();if(!a)throw new Error("No project configuration found");if(i=a.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}l.start("Loading function details...");let s=await n.getFunction(i);l.stop(),t.info(`\u{1F4CB} Logs for function: ${Ee.default.cyan(s.name)} (${Ui(s.status)})`),t.newline(),e.follow?await Kn(n,i,s.name,e):await Yi(n,i,e)}catch(n){l.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 f.load();let n=new j(f.getApiConfig()),i=o;if(!i){if(!f.isInProject())throw new Error("Function ID required. Provide as argument or run from function directory with sinch.json");let a=f.getProjectConfig();if(!a)throw new Error("No project configuration found");if(i=a.functionId,!i)throw new Error("No function ID found in sinch.json. Deploy the function first or provide function ID as argument.")}l.start("Connecting to log stream...");let s=await Li(n,i);l.stop(),await Kn(n,i,s.name,{...e,follow:!0})}catch(n){l.stop(),t.error(`Failed to stream logs: ${n.message}`),process.exit(1)}});async function Li(o,e){return await o.getFunction(e)}async function Kn(o,e,n,i){let s=o.baseUrl.replace(/\/+$/,""),a=o.projectId,r=`${s}/v1/projects/${a}/functions/${e}/logs/stream`,c=o.credentials,d=[],p=Wn(d,"STREAMING",n),u={Accept:"text/event-stream","Cache-Control":"no-cache"};if(c)try{let C=await c.retrieve();if(C&&C.keyId&&C.keySecret){let w=Buffer.from(`${C.keyId}:${C.keySecret}`).toString("base64");u.Authorization=`Basic ${w}`}}catch(C){t.debug("Failed to add authentication:",C)}let h=new AbortController;try{let C=await fetch(r,{method:"GET",headers:u,signal:h.signal});if(!C.ok)throw new Error(`SSE connection failed: ${C.status} ${C.statusText}`);if(!C.body)throw new Error("Response body is null");Jn(p.statusBar,"CONNECTED",n),p.screen.render();let w=C.body.getReader(),v=new TextDecoder,U="";(async()=>{try{for(;;){let{done:I,value:b}=await w.read();if(I)break;U+=v.decode(b,{stream:!0});let S=U.split(`
59
+ `);U=S.pop()||"";for(let y of S)if(!y.startsWith("event:")&&y.startsWith("data:")){let $=y.substring(5).trim();if($)try{let N=JSON.parse($);N.type==="request"&&N.request&&(d.push(N.request),Vn(p.table,N.request,d),p.table.focus(),p.screen.render())}catch{}}}}catch(I){I.name!=="AbortError"&&(Jn(p.statusBar,"RECONNECTING",n),p.screen.render())}})(),p.screen.key(["q","C-c"],()=>{h.abort(),process.exit(0)}),await new Promise(()=>{})}catch(C){h.abort(),t.error(`\u274C Streaming failed: ${C.message}`),process.exit(1)}}function Ui(o){return{Running:Ee.default.green("\u2705 Running"),Failed:Ee.default.red("\u274C Failed"),Pending:Ee.default.yellow("\u23F3 Pending"),Building:Ee.default.blue("\u{1F528} Building")}[o]||Ee.default.gray(o)}var je=[];function Vn(o,e,n){let i=new Date(e.startTime),s=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"),a=Hi(e),r=`${e.executionTimeMs}ms`,c=e.statusCode.toString(),d=process.stdout.columns||120,u=Math.max(30,d-35),h=e.url.length>u?e.url.substring(0,u-2)+"..":e.url;je.push([s,a,r,c,h]),je.length>100&&(je=je.slice(-100),n&&n.length>100&&n.splice(0,n.length-100));let C=[["Time","Callback","Duration","Status","Path"],...je];o.setData(C)}function Mi(o,e,n,i,s){try{let a=require("blessed");t.debug(`Showing request details for ${o.httpMethod} ${o.url}`);let r=a.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=a.box({parent:r,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"}});a.box({parent:r,top:2,left:2,width:"100%-4",height:1,content:`{bold}{cyan-fg}${o.httpMethod}{/} {blue-fg}${o.url}{/} - {${Wi(o.statusCode)}}${o.statusCode}{/} - {yellow-fg}${o.executionTimeMs}ms{/} - {magenta-fg}${o.memoryUsedMB||0}MB{/}`,tags:!0,style:{bg:"black"}});let d=a.box({parent:r,top:4,left:2,width:"100%-4",height:"100%-5",scrollable:!0,alwaysScroll:!0,keys:!0,vi:!0,tags:!0,content:Ji(o)});d.focus(),e.render();let p=!0,u=()=>{p&&(p=!1,r.destroy(),n.focus(),e.render())};e.key(["escape","q"],()=>{p&&u()}),e.key(["up","k"],()=>{p&&(d.scroll(-1),e.render())}),e.key(["down","j"],()=>{p&&(d.scroll(1),e.render())}),e.on("keypress",(h,C)=>{p&&t.debug(`Key pressed: ch="${h}" key=${JSON.stringify(C)}`)}),e.key(["J","j"],()=>{p&&(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"),ut(h).then(()=>{c.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded"),e.render(),setTimeout(()=>{p&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(C=>{t.debug(`Native clipboard failed: ${C.message}`);let w=et.default.join(Xe.default.tmpdir(),`sinch-request-${Date.now()}.json`);Ze.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 JSON saved to: ${w}{/}`),t.debug(`Saved to temp file: ${w}`),e.render(),setTimeout(()=>{p&&(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(()=>{p&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["C","c"],()=>{p&&(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=qn(o);t.debug("Attempting native clipboard copy for cURL"),ut(h).then(()=>{c.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),t.debug("Native clipboard copy succeeded for cURL"),e.render(),setTimeout(()=>{p&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(C=>{t.debug(`Native clipboard failed for cURL: ${C.message}`);let w=et.default.join(Xe.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);Ze.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 cURL saved to: ${w}{/}`),e.render(),setTimeout(()=>{p&&(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(()=>{p&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["1"],()=>{p&&(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);ut(h).then(()=>{c.setContent("{green-fg}\u2713 Request JSON copied to clipboard!{/}"),e.render(),setTimeout(()=>{p&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(C=>{let w=et.default.join(Xe.default.tmpdir(),`sinch-request-${Date.now()}.json`);Ze.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 JSON saved to: ${w}{/}`),e.render(),setTimeout(()=>{p&&(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(()=>{p&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))}),e.key(["2"],()=>{p&&(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=qn(o);ut(h).then(()=>{c.setContent("{green-fg}\u2713 cURL command copied to clipboard!{/}"),e.render(),setTimeout(()=>{p&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}).catch(C=>{let w=et.default.join(Xe.default.tmpdir(),`sinch-curl-${Date.now()}.sh`);Ze.default.writeFileSync(w,h),c.setContent(`{yellow-fg}\u2713 cURL saved to: ${w}{/}`),e.render(),setTimeout(()=>{p&&(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(()=>{p&&(c.setContent("{gray-fg}[Esc/Q] Close [\u2191\u2193] Scroll [J] JSON [C] cURL{/}"),e.render())},3e3)}},100))})}catch(a){t.debug(`Error in showBlessedZoomedRequest: ${a.message}`)}}function Ji(o){let e="";return e+=`
60
+ `,e+=qi(o),e+=`
61
+ `,e+=Bi(o),e+=`
62
+ `,e+=Ki(o),e}function qi(o){let e="",n=process.stdout.columns-6;e+="{bold}{green-fg}\u250C\u2500 REQUEST "+"\u2500".repeat(Math.max(0,n-10))+`\u2510{/}
63
+ `;let i=Gi(o);if(i&&(e+=`{green-fg}\u2502{/} {bold}Call ID:{/} {cyan-fg}${i}{/}
64
+ `),o.headers){e+=`{green-fg}\u2502{/} {bold}Headers:{/}
65
+ `;try{let s=typeof o.headers=="string"?JSON.parse(o.headers):o.headers;Object.entries(s).forEach(([a,r])=>{let c=` ${a}: ${r}`;e+=le(c,n-2,"{green-fg}\u2502{/} ")})}catch{e+=le(` ${o.headers}`,n-2,"{green-fg}\u2502{/} ")}}if(o.requestBody){e+=`{green-fg}\u2502{/} {bold}Body:{/}
66
+ `;try{let s=JSON.parse(o.requestBody);JSON.stringify(s,null,2).split(`
67
+ `).forEach(r=>{e+=le(r,n-2,"{green-fg}\u2502{/} ")})}catch{e+=le(o.requestBody,n-2,"{green-fg}\u2502{/} ")}}return e+="{green-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
68
+ `,e}function Bi(o){let e="",n=process.stdout.columns-6;if(e+="{bold}{blue-fg}\u250C\u2500 RESPONSE "+"\u2500".repeat(Math.max(0,n-11))+`\u2510{/}
69
+ `,o.responseHeaders){e+=`{blue-fg}\u2502{/} {bold}Headers:{/}
70
+ `;try{let i=typeof o.responseHeaders=="string"?JSON.parse(o.responseHeaders):o.responseHeaders;Object.entries(i).forEach(([s,a])=>{let r=` ${s}: ${a}`;e+=le(r,n-2,"{blue-fg}\u2502{/} ")})}catch{e+=le(` ${o.responseHeaders}`,n-2,"{blue-fg}\u2502{/} ")}}if(o.responseBody){e+=`{blue-fg}\u2502{/} {bold}Body:{/}
71
+ `;try{let i=JSON.parse(o.responseBody);JSON.stringify(i,null,2).split(`
72
+ `).forEach(a=>{e+=le(a,n-2,"{blue-fg}\u2502{/} ")})}catch{e+=le(o.responseBody,n-2,"{blue-fg}\u2502{/} ")}}return o.errorMessage&&(e+=`{blue-fg}\u2502{/} {bold}{red-fg}Error:{/}
73
+ `,e+=le(o.errorMessage,n-2,"{blue-fg}\u2502{/} ")),e+="{blue-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
74
+ `,e}function Ki(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{/}
75
+ `,o.logs&&o.logs.length>0?o.logs.forEach((i,s)=>{let a=new Date(i.timestamp).toLocaleTimeString(),r=i.level.toUpperCase().padEnd(5),c=Vi(i.level),d=`${a} [${r}] ${i.message}`;e+=le(d,n-2,"{magenta-fg}\u2502{/} ",c)}):e+=`{magenta-fg}\u2502{/} {gray-fg}No console logs for this request{/}
76
76
  `,e+="{magenta-fg}\u2514"+"\u2500".repeat(Math.max(0,n))+`\u2518{/}
77
- `,e}function ie(i,e,n,o=""){if(!i)return"";let s="";return i.split(`
78
- `).forEach(a=>{if(a.length<=e)s+=`${n}${o}${a}{/}
79
- `;else{let u=a,c=!0;for(;u.length>e;){let l=e-(c?0:4),p=u.substring(0,l);s+=`${n}${c?"":" "}${o}${p}{/}
80
- `,u=u.substring(l),c=!1}u.length>0&&(s+=`${n}${c?"":" "}${o}${u}{/}
81
- `)}}),s}function Qo(i){switch(i.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 Zo(i){return i>=200&&i<300?"green-fg":i>=300&&i<400?"yellow-fg":i>=400&&i<500?"red-fg":i>=500?"red-fg}{bold":"white-fg"}function Xo(i){try{if(i.requestBody){let e=JSON.parse(i.requestBody);return e.callId||e.callid||e.call_id||null}}catch{}return null}function ei(i){try{let e="";if(i.requestBody){let n=JSON.parse(i.requestBody);if(n.event)e=n.event.toLowerCase();else{let o=i.url.split("/").filter(s=>s);e=o[o.length-1]||""}return e||""}}catch{}return""}async function ti(i,e,n){try{d.start(`Loading ${n.lines} recent log entries...`);let o={limit:parseInt(n.lines||"50"),level:n.level,search:n.search};if(n.since){let a=ni(n.since);a&&(o.startTime=a.toISOString())}let s=await i.getFunctionLogs(e,o);if(d.stop(),t.debug("Historical API response:",{totalRequests:s.requests?.length||0,firstRequest:s.requests?.[0]||"No requests",responseKeys:Object.keys(s)}),!s.requests||s.requests.length===0){t.info("\u{1F4DD} No logs found"),t.info("\u{1F4A1} Logs will appear here after function receives requests");return}let r=s.requests;t.debug("Historical requests:",{totalRequests:r.length,firstRequest:r[0]||"No requests",requestTimestamps:r.slice(0,3).map(a=>a.startTime)}),await oi(r,"HISTORICAL","Function")}catch(o){throw d.stop(),o}}function ni(i){if(!i)return null;let e=i.match(/^(\d+)([smhd])$/);if(!e)return null;let n=parseInt(e[1]),o=e[2],s=new Date;switch(o){case"s":return new Date(s.getTime()-n*1e3);case"m":return new Date(s.getTime()-n*60*1e3);case"h":return new Date(s.getTime()-n*60*60*1e3);case"d":return new Date(s.getTime()-n*24*60*60*1e3);default:return null}}async function oi(i,e,n){let o=An(i,e,n);i.forEach(s=>{In(o.table,s,i)}),o.screen.render(),await new Promise(()=>{})}function An(i,e,n){let o=require("blessed");process.stdout.write("\x1Bc"),$e=[];let s=o.screen({smartCSR:!0,title:`Sinch Functions - ${n} Logs`,fullUnicode:!0}),r=o.box({parent:s,top:0,left:0,width:"100%",height:1,content:Rn(e,n),tags:!0,style:{bg:"black"}}),a=o.listtable({parent:s,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}),u=["Time","Callback","Duration","Status","Path"];a.setData([u]),a.focus(),s.key(["q","C-c"],()=>{process.exit(0)});let c=()=>{try{let l=a.selected||0,p=l-1;if(p>=0&&p<i.length&&i[p])t.debug(`Opening request details for index ${p}`),Wo(i[p],s,a,r,n);else{let m=`Selected: ${l}, DataIndex: ${p}, Requests: ${i.length}, TableData: ${$e.length}`;t.debug(`Selection out of bounds: ${m}`)}}catch(l){t.debug(`Error in request selection: ${l.message}`)}};return s.key(["enter"],c),a.on("select",(l,p)=>{c()}),s.on("wheelup",()=>{a.focused&&(a.scroll(-1),s.render())}),s.on("wheeldown",()=>{a.focused&&(a.scroll(1),s.render())}),{screen:s,table:a,statusBar:r}}function Rn(i,e){switch(i){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 $n(i,e,n){i.setContent(Rn(e,n))}function et(i){return new Promise((e,n)=>{let o,s;process.platform==="win32"?(o="clip",s=[]):process.platform==="darwin"?(o="pbcopy",s=[]):(o="xclip",s=["-selection","clipboard"]),t.debug(`Using clipboard command: ${o} with args:`,s);let r=(0,vt.spawn)(o,s,{stdio:["pipe","ignore","pipe"]}),a="";r.stderr.on("data",u=>{a+=u.toString()}),r.on("error",u=>{if(t.debug(`Clipboard process error: ${u.message}`),process.platform==="linux"&&o==="xclip"){t.debug("Trying xsel as fallback");let c=(0,vt.spawn)("xsel",["--clipboard","--input"],{stdio:["pipe","ignore","pipe"]});c.on("error",l=>{n(new Error(`No clipboard utility found: ${u.message} / ${l.message}`))}),c.on("close",l=>{l===0?e():n(new Error(`xsel failed with code ${l}`))}),c.stdin&&(c.stdin.write(i),c.stdin.end());return}n(u)}),r.on("close",u=>{u===0?(t.debug("Clipboard copy successful"),e()):(t.debug(`Clipboard process failed with code ${u}, error: ${a}`),n(new Error(`Clipboard command failed with code ${u}: ${a}`)))}),r.stdin&&(r.stdin.write(i),r.stdin.end())})}function kn(i){let e=process.platform==="win32",n=`curl -X ${i.httpMethod}`,o={};if(i.headers)try{o=typeof i.headers=="string"?JSON.parse(i.headers):i.headers}catch{}let s=i.url;if(s&&!s.startsWith("http")){let r=o.host||o.Host;r&&(s=`${r.includes("localhost")||r.includes("127.0.0.1")?"http":"https"}://${r}${s.startsWith("/")?s:"/"+s}`)}if(n+=` "${s}"`,Object.entries(o).forEach(([r,a])=>{let u=["content-length","connection","user-agent"];i.url.startsWith("http")||u.push("host"),u.includes(r.toLowerCase())||(e?n+=` -H "${r}: ${a}"`:n+=` \\
82
- -H "${r}: ${a}"`)}),i.requestBody&&["POST","PUT","PATCH"].includes(i.httpMethod)){try{let r=JSON.parse(i.requestBody),a=JSON.stringify(r);e?n+=` -d '${a.replace(/'/g,"\\'")}'`:n+=` \\
83
- -d '${JSON.stringify(r,null,2)}'`}catch{e?n+=` -d '${i.requestBody.replace(/'/g,"\\'")}'`:n+=` \\
84
- -d '${i.requestBody}'`}n.toLowerCase().includes("content-type")||(e?n+=' -H "Content-Type: application/json"':n+=` \\
77
+ `,e}function le(o,e,n,i=""){if(!o)return"";let s="";return o.split(`
78
+ `).forEach(r=>{if(r.length<=e)s+=`${n}${i}${r}{/}
79
+ `;else{let c=r,d=!0;for(;c.length>e;){let p=e-(d?0:4),u=c.substring(0,p);s+=`${n}${d?"":" "}${i}${u}{/}
80
+ `,c=c.substring(p),d=!1}c.length>0&&(s+=`${n}${d?"":" "}${i}${c}{/}
81
+ `)}}),s}function Vi(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 Wi(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 Gi(o){try{if(o.requestBody){let e=JSON.parse(o.requestBody);return e.callId||e.callid||e.call_id||null}}catch{}return null}function Hi(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(s=>s);e=i[i.length-1]||""}return e||""}}catch{}return""}async function Yi(o,e,n){try{l.start(`Loading ${n.lines} recent log entries...`);let i={limit:parseInt(n.lines||"50"),level:n.level,search:n.search};if(n.since){let r=zi(n.since);r&&(i.startTime=r.toISOString())}let s=await o.getFunctionLogs(e,i);if(l.stop(),t.debug("Historical API response:",{totalRequests:s.requests?.length||0,firstRequest:s.requests?.[0]||"No requests",responseKeys:Object.keys(s)}),!s.requests||s.requests.length===0){t.info("\u{1F4DD} No logs found"),t.info("\u{1F4A1} Logs will appear here after function receives requests");return}let a=s.requests;t.debug("Historical requests:",{totalRequests:a.length,firstRequest:a[0]||"No requests",requestTimestamps:a.slice(0,3).map(r=>r.startTime)}),await Qi(a,"HISTORICAL","Function")}catch(i){throw l.stop(),i}}function zi(o){if(!o)return null;let e=o.match(/^(\d+)([smhd])$/);if(!e)return null;let n=parseInt(e[1]),i=e[2],s=new Date;switch(i){case"s":return new Date(s.getTime()-n*1e3);case"m":return new Date(s.getTime()-n*60*1e3);case"h":return new Date(s.getTime()-n*60*60*1e3);case"d":return new Date(s.getTime()-n*24*60*60*1e3);default:return null}}async function Qi(o,e,n){let i=Wn(o,e,n);o.forEach(s=>{Vn(i.table,s,o)}),i.screen.render(),await new Promise(()=>{})}function Wn(o,e,n){let i=require("blessed");process.stdout.write("\x1Bc"),je=[];let s=i.screen({smartCSR:!0,title:`Sinch Functions - ${n} Logs`,fullUnicode:!0}),a=i.box({parent:s,top:0,left:0,width:"100%",height:1,content:Gn(e,n),tags:!0,style:{bg:"black"}}),r=i.listtable({parent:s,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"];r.setData([c]),r.focus(),s.key(["q","C-c"],()=>{process.exit(0)});let d=()=>{try{let p=r.selected||0,u=p-1;if(u>=0&&u<o.length&&o[u])t.debug(`Opening request details for index ${u}`),Mi(o[u],s,r,a,n);else{let h=`Selected: ${p}, DataIndex: ${u}, Requests: ${o.length}, TableData: ${je.length}`;t.debug(`Selection out of bounds: ${h}`)}}catch(p){t.debug(`Error in request selection: ${p.message}`)}};return s.key(["enter"],d),r.on("select",(p,u)=>{d()}),s.on("wheelup",()=>{r.focused&&(r.scroll(-1),s.render())}),s.on("wheeldown",()=>{r.focused&&(r.scroll(1),s.render())}),{screen:s,table:r,statusBar:a}}function Gn(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 Jn(o,e,n){o.setContent(Gn(e,n))}function ut(o){return new Promise((e,n)=>{let i,s;process.platform==="win32"?(i="clip",s=[]):process.platform==="darwin"?(i="pbcopy",s=[]):(i="xclip",s=["-selection","clipboard"]),t.debug(`Using clipboard command: ${i} with args:`,s);let a=(0,Nt.spawn)(i,s,{stdio:["pipe","ignore","pipe"]}),r="";a.stderr.on("data",c=>{r+=c.toString()}),a.on("error",c=>{if(t.debug(`Clipboard process error: ${c.message}`),process.platform==="linux"&&i==="xclip"){t.debug("Trying xsel as fallback");let d=(0,Nt.spawn)("xsel",["--clipboard","--input"],{stdio:["pipe","ignore","pipe"]});d.on("error",p=>{n(new Error(`No clipboard utility found: ${c.message} / ${p.message}`))}),d.on("close",p=>{p===0?e():n(new Error(`xsel failed with code ${p}`))}),d.stdin&&(d.stdin.write(o),d.stdin.end());return}n(c)}),a.on("close",c=>{c===0?(t.debug("Clipboard copy successful"),e()):(t.debug(`Clipboard process failed with code ${c}, error: ${r}`),n(new Error(`Clipboard command failed with code ${c}: ${r}`)))}),a.stdin&&(a.stdin.write(o),a.stdin.end())})}function qn(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 s=o.url;if(s&&!s.startsWith("http")){let a=i.host||i.Host;a&&(s=`${a.includes("localhost")||a.includes("127.0.0.1")?"http":"https"}://${a}${s.startsWith("/")?s:"/"+s}`)}if(n+=` "${s}"`,Object.entries(i).forEach(([a,r])=>{let c=["content-length","connection","user-agent"];o.url.startsWith("http")||c.push("host"),c.includes(a.toLowerCase())||(e?n+=` -H "${a}: ${r}"`:n+=` \\
82
+ -H "${a}: ${r}"`)}),o.requestBody&&["POST","PUT","PATCH"].includes(o.httpMethod)){try{let a=JSON.parse(o.requestBody),r=JSON.stringify(a);e?n+=` -d '${r.replace(/'/g,"\\'")}'`:n+=` \\
83
+ -d '${JSON.stringify(a,null,2)}'`}catch{e?n+=` -d '${o.requestBody.replace(/'/g,"\\'")}'`:n+=` \\
84
+ -d '${o.requestBody}'`}n.toLowerCase().includes("content-type")||(e?n+=' -H "Content-Type: application/json"':n+=` \\
85
85
  -H "Content-Type: application/json"`)}return e?n+=" -v":n+=` \\
86
- -v`,n}jn.exports=$t});var Ln=K((Ds,_n)=>{"use strict";var M=h(require("chalk")),Dn=h(require("inquirer")),On=require("commander");U();j();B();L();var Fn=new On.Command("delete");Fn.alias("del").description("Delete a function").argument("<function-id>","Function ID to delete").option("-f, --force","Skip confirmation").action(async(i,e)=>{try{await f.load();let n=new A(f.getApiConfig());d.start("Loading function details...");let o=await n.getFunction(i);if(d.stop(),t.newline(),t.info("\u{1F5D1}\uFE0F Function to delete:"),t.info(` Name: ${M.default.cyan(o.name)}`),t.info(` ID: ${M.default.gray(o.id)}`),t.info(` Runtime: ${M.default.yellow(o.runtime)}`),t.info(` Status: ${ii(o.status)}`),t.info(` Created: ${new Date(o.createdAt).toLocaleString()}`),o.containerAppUrl&&t.info(` URL: ${M.default.blue(o.containerAppUrl)}`),!e.force){t.newline(),t.warn("\u26A0\uFE0F This action cannot be undone!");let{confirm:s}=await Dn.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete function '${o.name}'?`,default:!1}]);if(!s){t.info("Deletion cancelled");return}}d.start("Deleting function..."),await n.deleteFunction(i),d.succeed(`Function '${o.name}' deleted successfully`),f.isInProject()&&f.getProjectConfig()?.functionId===i&&(f.set("functionId",void 0,!0),await f.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 '${i}' 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 ii(i){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")}[i]||M.default.gray(i)}_n.exports=Fn});var Un=K((Ns,Nn)=>{"use strict";var xn=require("commander"),kt=h(require("fs-extra")),Pt=h(require("path")),ke=h(require("chalk"));j();B();L();wt();U();var Et=new xn.Command("docs");Et.description("Generate documentation for voice functions (saves to README.md)");Et.option("-f, --fresh","Force regeneration (skip cache)").option("-u, --update","Update documentation for deployed function via API").action(async i=>{try{await f.load(),i.update?await ri():await si(i)}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 si(i){d.start("\u{1F916} Generating documentation...");let e=await ht();d.succeed("\u2705 Documentation generated!"),await yt(e,"README.md"),await ai()}async function ri(){let i=Pt.default.basename(process.cwd());d.start("\u{1F4D6} Reading local README.md...");let e=Pt.default.join(process.cwd(),"README.md");if(!await kt.default.pathExists(e))throw new Error("README.md not found. Run `sinch functions docs` first to generate documentation locally.");if(!(await kt.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 r=(await new A(f.getApiConfig()).listFunctions()).find(a=>a.name===i);if(!r)throw new Error(`Function '${i}' 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: ${ke.default.cyan(i)}`),t.info(""),t.info("\u2728 Your function documentation has been updated:"),t.info(` \u2022 Function ID: ${ke.default.gray(r.id)}`),t.info(` \u2022 Source: ${ke.default.gray("Local README.md")}`),t.info(` \u2022 Updated: ${ke.default.gray(new Date().toLocaleString())}`),t.info(` \u2022 View in dashboard: ${ke.default.cyan("Dashboard \u2192 Functions \u2192 "+i)}`),t.newline(),t.info("\u{1F4A1} The updated documentation is now available in the dashboard!")}async function ai(){t.newline(),t.success(`\u{1F4C4} Documentation updated in: ${ke.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")}Nn.exports=Et});var Jn=K((qs,qn)=>{"use strict";var x=h(require("chalk")),It=h(require("inquirer")),Bn=require("commander"),X=h(require("fs-extra")),fe=h(require("path")),Kn=h(require("adm-zip"));U();j();B();L();var Vn=new Bn.Command("download");Vn.description("Download function source code").argument("[function-id]","Function ID to download (ULID format)").option("-o, --output <dir>","Output directory (default: ./functions/<function-name>)").option("--no-extract","Keep as ZIP file without extracting").option("--non-interactive","Skip interactive selection").option("-f, --force","Overwrite existing directory without prompting").action(async(i,e)=>{try{await f.load();let n=new A(f.getApiConfig()),o=i;if(!o&&!e.nonInteractive){let l=await ci(n);if(!l){t.info("Download cancelled");return}o=l}o||(t.error("Function ID required. Provide as argument or select interactively"),t.info(`Usage: ${x.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABCDE")}`),t.info(` or: ${x.default.cyan("sinch functions download")} (interactive selection)`),process.exit(1)),d.start("\u{1F4E1} Fetching function metadata...");let s=await n.getFunction(o);d.succeed("Function metadata loaded");let r=fe.join("functions",s.name),a=e.output||r,u=fe.resolve(a);if(await X.pathExists(u)){if(!e.force){let{overwrite:l}=await It.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${a}' already exists. Overwrite?`,default:!1}]);if(!l){t.info("Download cancelled");return}}d.start("\u{1F5D1}\uFE0F Removing existing directory..."),await X.remove(u),d.succeed("Existing directory removed")}d.start("\u{1F4E5} Downloading function source code...");let c=await n.downloadFunction(o);if(d.succeed("Source code downloaded"),e.extract!==!1){d.start("\u{1F4E6} Extracting files..."),await X.ensureDir(u);let l=new Kn.default(c),p=l.getEntries();l.extractAllTo(u,!0),d.succeed(`\u{1F4E6} Extracted ${p.length} files`);let m=fe.join(u,"sinch-metadata.json"),C={functionId:s.id,name:s.name,runtime:s.runtime,status:s.status,downloadedAt:new Date().toISOString(),url:s.containerAppUrl,configuration:s.configuration};await X.writeJson(m,C,{spaces:2}),t.newline(),t.success("\u2705 Function downloaded successfully!"),t.newline(),t.info(`\u{1F4C1} Location: ${x.default.cyan(a)}`),t.info(`\u{1F4CB} Files: ${p.length} files extracted`);let w=fe.join(u,"sinch.json");await X.pathExists(w)&&t.info("\u{1F527} Config: sinch.json found"),t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 Navigate: ${x.default.cyan(`cd ${a}`)}`),t.info(` \u2022 Run locally: ${x.default.cyan("sinch functions dev")}`),t.info(` \u2022 Deploy changes: ${x.default.cyan("sinch functions deploy")}`)}else{let l=`${s.name}.zip`,p=e.output?fe.resolve(e.output):fe.resolve(l);d.start(`\u{1F4BE} Saving as ${l}...`),await X.writeFile(p,c),d.succeed("ZIP file saved"),t.newline(),t.success("\u2705 Function downloaded as ZIP!"),t.info(`\u{1F4C1} File: ${x.default.cyan(p)}`),t.info(`\u{1F4E6} Size: ${(c.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: ${i}`),t.info("\u{1F4A1} List available functions with:"),t.info(` ${x.default.cyan("sinch functions list")}`),t.info("\u{1F4A1} Or use interactive selection:"),t.info(` ${x.default.cyan("sinch functions download")}`)):t.error(`Failed to download function: ${n.message}`),process.exit(1)}});async function ci(i){try{d.start("\u{1F4CB} Loading functions...");let e=await i.listFunctions();if(d.stop(),!e.functions||e.functions.length===0)return t.warn("No functions found to download"),null;let n=e.functions.map(s=>({name:`${x.default.cyan(s.name.padEnd(20))} ${x.default.yellow(s.runtime.padEnd(8))} ${li(s.status)}`,value:s.id,short:s.name}));t.newline();let{selectedFunction:o}=await It.default.prompt([{type:"list",name:"selectedFunction",message:"Select a function to download:",choices:n,pageSize:15}]);return o}catch(e){throw d.stop(),e}}function li(i){return{Running:x.default.green("\u2705 Running"),Failed:x.default.red("\u274C Failed"),Pending:x.default.yellow("\u23F3 Pending"),Building:x.default.blue("\u{1F528} Building")}[i]||x.default.gray(i)}qn.exports=Vn});var Hn=K((Js,Wn)=>{"use strict";var Mn=require("commander"),ui=Wt(),di=Qt(),pi=pn(),fi=yn(),gi=vn(),mi=Tn(),hi=Ln(),yi=Un(),wi=Jn(),ee=new Mn.Command("functions");ee.description("Manage Sinch Functions");ee.addCommand(ui);ee.addCommand(di);ee.addCommand(pi);ee.addCommand(wi);ee.addCommand(fi);ee.addCommand(gi);ee.addCommand(mi);ee.addCommand(hi);ee.addCommand(yi);Wn.exports=ee});var zn=K((Ys,Yn)=>{"use strict";var Gn=require("commander"),W=h(require("chalk"));U();j();B();L();var se=new Gn.Command("templates");se.description("Browse and manage function templates");se.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(i,e)=>{try{await f.load();let n=new A(f.getApiConfig());d.start("Loading templates...");let o;if(i?o=await n.listRuntimeTemplates(i,e.category):o=await n.listAllTemplates(e.category),d.stop(),o.templates.length===0){t.info(`No templates found${i?` for ${i}`:""}${e.category?` in category ${e.category}`:""}`);return}let s=`Available Templates${i?` (${i})`:""}${e.category?` - ${e.category}`:""}`;if(t.title(s),e.detailed)o.templates.forEach((r,a)=>{a>0&&t.newline(),t.log(W.default.bold.blue(`${r.name}`)),t.log(` Runtime: ${r.runtime}`),t.log(` Category: ${r.category}`),t.log(` Description: ${r.description}`),r.tags&&r.tags.length>0&&t.log(` Tags: ${r.tags.map(u=>W.default.gray(u)).join(", ")}`),t.log(` Path: ${W.default.gray(r.path)}`)});else{let r=o.templates.map(a=>[a.name,a.runtime,a.category,a.description.substring(0,50)+(a.description.length>50?"...":""),a.tags?a.tags.slice(0,2).join(", ")+(a.tags.length>2?"...":""):""]);t.table(["Name","Runtime","Category","Description","Tags"],r)}t.newline(),t.info(`Found ${o.templates.length} template${o.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)}});se.command("show").description("Show detailed template information").argument("<template>",'Template name in format "runtime/template-name"').action(async i=>{try{await f.load();let e=new A(f.getApiConfig());if(!i.includes("/"))throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');let n=i.split("/"),o=n[0],s=n[1];if(!o||!s)throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');d.start(`Loading template details for ${i}...`);let r=await e.getTemplateDetails(o,s);d.stop(),t.title(`Template: ${r.name}`),t.newline(),t.log(W.default.bold("Basic Information:")),t.log(` Runtime: ${r.runtime}`),t.log(` Category: ${r.category}`),t.log(` Description: ${r.description}`),r.tags&&r.tags.length>0&&t.log(` Tags: ${r.tags.map(a=>W.default.blue(a)).join(", ")}`),r.variables&&Object.keys(r.variables).length>0&&(t.newline(),t.log(W.default.bold("Template Variables:")),Object.entries(r.variables).forEach(([a,u])=>{t.log(` ${a}: ${W.default.gray(u)}`)})),r.files&&r.files.length>0&&(t.newline(),t.log(W.default.bold("Files:")),r.files.forEach(a=>{t.log(` ${W.default.gray("\u2022")} ${a}`)})),r.readmeContent&&(t.newline(),t.log(W.default.bold("README:")),r.readmeContent.split(`
87
- `).slice(0,10).forEach(u=>{t.log(` ${W.default.gray(u)}`)}),r.readmeContent.split(`
88
- `).length>10&&t.log(` ${W.default.gray("... (truncated)")}`)),t.newline(),t.info(`Use "sinch functions init --template ${i}" to create a function from this template`)}catch(e){d.stop(),t.error(`Failed to show template details: ${e.message}`),process.exit(1)}});se.command("node").description("List Node.js templates").option("-c, --category <category>","Filter by category").action(async i=>{let e=se.commands.find(n=>n.name()==="list");e&&await e.action("node",i)});se.command("csharp").description("List C# templates").option("-c, --category <category>","Filter by category").action(async i=>{let e=se.commands.find(n=>n.name()==="list");e&&await e.action("csharp",i)});se.command("python").description("List Python templates").option("-c, --category <category>","Filter by category").action(async i=>{let e=se.commands.find(n=>n.name()==="list");e&&await e.action("python",i)});Yn.exports=se});var eo=K((Xs,Xn)=>{"use strict";var Qn=require("commander"),Pe=h(require("chalk")),Zn=h(require("inquirer"));j();B();L();var Je=new Qn.Command("voice");Je.description("Manage Sinch Voice applications and settings");Je.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(i,e)=>{try{await f.load(),await At()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await Ci(),o=e.appKey;if(!o){let s=f.getPublicCredentialInfo()?.applicationKey;s||(t.error('No default application key found. Run "sinch auth login" first.'),process.exit(1)),o=s,t.info(`Using default application: ${o}`)}if(!i){let{newUrl:s}=await Zn.default.prompt([{type:"input",name:"newUrl",message:"Enter new callback URL:",validate:r=>{if(!r)return"URL is required";try{return new URL(r),!0}catch{return"Please enter a valid URL"}}}]);i=s}d.start("Updating callback URL...");try{let s=await n.voice.applications.get(o),r={...s,capability:{...s.capability,voice:{...s.capability?.voice,webhooks:{...s.capability?.voice?.webhooks,url:i,method:"POST"}}}};await n.voice.applications.update(o,r),d.succeed("Callback URL updated successfully!"),t.newline(),t.info(`Application: ${s.displayName||o}`),t.info(`New callback URL: ${i}`),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(s){throw d.fail("Failed to update callback URL"),s}}catch(n){d.stop(),t.error(`Failed to update callback URL: ${n.message}`),process.exit(1)}});Je.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 i=>{try{await f.load(),await At()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=await f.getApplicationCredentials();e||(t.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let n=i.appKey||e.applicationKey;if(t.info("\u{1F50D} Getting callback URLs..."),t.newline(),i.curl){let o=`${e.applicationKey}:${e.applicationSecret}`,s=Buffer.from(o).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(Pe.default.gray("```bash"));let r=`curl -X GET \\
86
+ -v`,n}Hn.exports=Ft});var eo=F((Fr,Xn)=>{"use strict";var Y=m(require("chalk")),zn=m(require("inquirer")),Qn=require("commander");K();D();_();T();var Zn=new Qn.Command("delete");Zn.alias("del").description("Delete a function").argument("<function-id>","Function ID to delete").option("-f, --force","Skip confirmation").action(async(o,e)=>{try{await f.load();let n=new j(f.getApiConfig());l.start("Loading function details...");let i=await n.getFunction(o);if(l.stop(),t.newline(),t.info("\u{1F5D1}\uFE0F Function to delete:"),t.info(` Name: ${Y.default.cyan(i.name)}`),t.info(` ID: ${Y.default.gray(i.id)}`),t.info(` Runtime: ${Y.default.yellow(i.runtime)}`),t.info(` Status: ${Zi(i.status)}`),t.info(` Created: ${new Date(i.createdAt).toLocaleString()}`),i.containerAppUrl&&t.info(` URL: ${Y.default.blue(i.containerAppUrl)}`),!e.force){t.newline(),t.warn("\u26A0\uFE0F This action cannot be undone!");let{confirm:s}=await zn.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete function '${i.name}'?`,default:!1}]);if(!s){t.info("Deletion cancelled");return}}l.start("Deleting function..."),await n.deleteFunction(o),l.succeed(`Function '${i.name}' deleted successfully`),f.isInProject()&&f.getProjectConfig()?.functionId===o&&(f.set("functionId",void 0,!0),await f.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: ${Y.default.cyan("sinch functions list")}`),t.info(` \u2022 Deploy new function: ${Y.default.cyan("sinch functions deploy")}`)}catch(n){l.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(` ${Y.default.cyan("sinch functions list")}`)):t.error(`Failed to delete function: ${n.message}`),process.exit(1)}});function Zi(o){return{Running:Y.default.green("\u2705 Running"),Failed:Y.default.red("\u274C Failed"),Pending:Y.default.yellow("\u23F3 Pending"),Building:Y.default.blue("\u{1F528} Building")}[o]||Y.default.gray(o)}Xn.exports=Zn});var oo=F((qr,no)=>{"use strict";var to=require("commander"),xt=m(require("fs-extra")),Lt=m(require("path")),Re=m(require("chalk"));D();_();T();Ot();K();var Ut=new to.Command("docs");Ut.description("Generate documentation for voice functions (saves to README.md)");Ut.option("-f, --fresh","Force regeneration (skip cache)").option("-u, --update","Update documentation for deployed function via API").action(async o=>{try{await f.load(),o.update?await es():await Xi(o)}catch(e){l.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 Xi(o){l.start("\u{1F916} Generating documentation...");let e=await jt();l.succeed("\u2705 Documentation generated!"),await Rt(e,"README.md"),await ts()}async function es(){let o=Lt.default.basename(process.cwd());l.start("\u{1F4D6} Reading local README.md...");let e=Lt.default.join(process.cwd(),"README.md");if(!await xt.default.pathExists(e))throw new Error("README.md not found. Run `sinch functions docs` first to generate documentation locally.");if(!(await xt.default.readFile(e,"utf8")).trim())throw new Error("README.md is empty. Run `sinch functions docs` first to generate documentation.");l.text="\u{1F50D} Finding deployed function...";let a=(await new j(f.getApiConfig()).listFunctions()).find(r=>r.name===o);if(!a)throw new Error(`Function '${o}' not found in project. Make sure it's deployed first.`);l.text="\u{1F4E4} Uploading documentation content...",t.info("Documentation content ready for update"),l.succeed("\u2705 Documentation updated!"),t.newline(),t.success(`\u{1F4C4} Documentation updated for deployed function: ${Re.default.cyan(o)}`),t.info(""),t.info("\u2728 Your function documentation has been updated:"),t.info(` \u2022 Function ID: ${Re.default.gray(a.id)}`),t.info(` \u2022 Source: ${Re.default.gray("Local README.md")}`),t.info(` \u2022 Updated: ${Re.default.gray(new Date().toLocaleString())}`),t.info(` \u2022 View in dashboard: ${Re.default.cyan("Dashboard \u2192 Functions \u2192 "+o)}`),t.newline(),t.info("\u{1F4A1} The updated documentation is now available in the dashboard!")}async function ts(){t.newline(),t.success(`\u{1F4C4} Documentation updated in: ${Re.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")}no.exports=Ut});var co=F((Gr,ao)=>{"use strict";var q=m(require("chalk")),Mt=m(require("inquirer")),io=require("commander"),ie=m(require("fs-extra")),ye=m(require("path")),so=m(require("adm-zip"));K();D();_();T();var ro=new io.Command("download");ro.description("Download function source code").argument("[function-id]","Function ID to download (ULID format)").option("-o, --output <dir>","Output directory (default: ./functions/<function-name>)").option("--no-extract","Keep as ZIP file without extracting").option("--non-interactive","Skip interactive selection").option("-f, --force","Overwrite existing directory without prompting").action(async(o,e)=>{try{await f.load();let n=new j(f.getApiConfig()),i=o;if(!i&&!e.nonInteractive){let p=await ns(n);if(!p){t.info("Download cancelled");return}i=p}i||(t.error("Function ID required. Provide as argument or select interactively"),t.info(`Usage: ${q.default.cyan("sinch functions download 01HX3KC5V8G3KCNZ8S5Y9ABCDE")}`),t.info(` or: ${q.default.cyan("sinch functions download")} (interactive selection)`),process.exit(1)),l.start("\u{1F4E1} Fetching function metadata...");let s=await n.getFunction(i);l.succeed("Function metadata loaded");let a=ye.join("functions",s.name),r=e.output||a,c=ye.resolve(r);if(await ie.pathExists(c)){if(!e.force){let{overwrite:p}=await Mt.default.prompt([{type:"confirm",name:"overwrite",message:`Directory '${r}' already exists. Overwrite?`,default:!1}]);if(!p){t.info("Download cancelled");return}}l.start("\u{1F5D1}\uFE0F Removing existing directory..."),await ie.remove(c),l.succeed("Existing directory removed")}l.start("\u{1F4E5} Downloading function source code...");let d=await n.downloadFunction(i);if(l.succeed("Source code downloaded"),e.extract!==!1){l.start("\u{1F4E6} Extracting files..."),await ie.ensureDir(c);let p=new so.default(d),u=p.getEntries();p.extractAllTo(c,!0),l.succeed(`\u{1F4E6} Extracted ${u.length} files`);let h=ye.join(c,"sinch-metadata.json"),C={functionId:s.id,name:s.name,runtime:s.runtime,status:s.status,downloadedAt:new Date().toISOString(),url:s.containerAppUrl,configuration:s.configuration};await ie.writeJson(h,C,{spaces:2}),t.newline(),t.success("\u2705 Function downloaded successfully!"),t.newline(),t.info(`\u{1F4C1} Location: ${q.default.cyan(r)}`),t.info(`\u{1F4CB} Files: ${u.length} files extracted`);let w=ye.join(c,"sinch.json");await ie.pathExists(w)&&t.info("\u{1F527} Config: sinch.json found"),t.newline(),t.info("\u{1F4A1} Next steps:"),t.info(` \u2022 Navigate: ${q.default.cyan(`cd ${r}`)}`),t.info(` \u2022 Run locally: ${q.default.cyan("sinch functions dev")}`),t.info(` \u2022 Deploy changes: ${q.default.cyan("sinch functions deploy")}`)}else{let p=`${s.name}.zip`,u=e.output?ye.resolve(e.output):ye.resolve(p);l.start(`\u{1F4BE} Saving as ${p}...`),await ie.writeFile(u,d),l.succeed("ZIP file saved"),t.newline(),t.success("\u2705 Function downloaded as ZIP!"),t.info(`\u{1F4C1} File: ${q.default.cyan(u)}`),t.info(`\u{1F4E6} Size: ${(d.length/1024).toFixed(2)} KB`)}}catch(n){l.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(` ${q.default.cyan("sinch functions list")}`),t.info("\u{1F4A1} Or use interactive selection:"),t.info(` ${q.default.cyan("sinch functions download")}`)):t.error(`Failed to download function: ${n.message}`),process.exit(1)}});async function ns(o){try{l.start("\u{1F4CB} Loading functions...");let e=await o.listFunctions();if(l.stop(),!e.functions||e.functions.length===0)return t.warn("No functions found to download"),null;let n=e.functions.map(s=>({name:`${q.default.cyan(s.name.padEnd(20))} ${q.default.yellow(s.runtime.padEnd(8))} ${os(s.status)}`,value:s.id,short:s.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 l.stop(),e}}function os(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)}ao.exports=ro});var uo=F((Hr,po)=>{"use strict";var lo=require("commander"),is=pn(),ss=hn(),rs=Rn(),as=Nn(),cs=Mn(),ls=Yn(),ds=eo(),ps=oo(),us=co(),se=new lo.Command("functions");se.description("Manage Sinch Functions");se.addCommand(is);se.addCommand(ss);se.addCommand(rs);se.addCommand(us);se.addCommand(as);se.addCommand(cs);se.addCommand(ls);se.addCommand(ds);se.addCommand(ps);po.exports=se});var mo=F((Xr,go)=>{"use strict";var fo=require("commander"),z=m(require("chalk"));K();D();_();T();var de=new fo.Command("templates");de.description("Browse and manage function templates");de.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 f.load();let n=new j(f.getApiConfig());l.start("Loading templates...");let i;if(o?i=await n.listRuntimeTemplates(o,e.category):i=await n.listAllTemplates(e.category),l.stop(),i.templates.length===0){t.info(`No templates found${o?` for ${o}`:""}${e.category?` in category ${e.category}`:""}`);return}let s=`Available Templates${o?` (${o})`:""}${e.category?` - ${e.category}`:""}`;if(t.title(s),e.detailed)i.templates.forEach((a,r)=>{r>0&&t.newline(),t.log(z.default.bold.blue(`${a.name}`)),t.log(` Runtime: ${a.runtime}`),t.log(` Category: ${a.category}`),t.log(` Description: ${a.description}`),a.tags&&a.tags.length>0&&t.log(` Tags: ${a.tags.map(c=>z.default.gray(c)).join(", ")}`),t.log(` Path: ${z.default.gray(a.path)}`)});else{let a=i.templates.map(r=>[r.name,r.runtime,r.category,r.description.substring(0,50)+(r.description.length>50?"...":""),r.tags?r.tags.slice(0,2).join(", ")+(r.tags.length>2?"...":""):""]);t.table(["Name","Runtime","Category","Description","Tags"],a)}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){l.stop(),t.error(`Failed to list templates: ${n.message}`),process.exit(1)}});de.command("show").description("Show detailed template information").argument("<template>",'Template name in format "runtime/template-name"').action(async o=>{try{await f.load();let e=new j(f.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],s=n[1];if(!i||!s)throw new Error('Template must be in format "runtime/template-name" (e.g., "node/simple-voice-ivr")');l.start(`Loading template details for ${o}...`);let a=await e.getTemplateDetails(i,s);l.stop(),t.title(`Template: ${a.name}`),t.newline(),t.log(z.default.bold("Basic Information:")),t.log(` Runtime: ${a.runtime}`),t.log(` Category: ${a.category}`),t.log(` Description: ${a.description}`),a.tags&&a.tags.length>0&&t.log(` Tags: ${a.tags.map(r=>z.default.blue(r)).join(", ")}`),a.variables&&Object.keys(a.variables).length>0&&(t.newline(),t.log(z.default.bold("Template Variables:")),Object.entries(a.variables).forEach(([r,c])=>{t.log(` ${r}: ${z.default.gray(c)}`)})),a.files&&a.files.length>0&&(t.newline(),t.log(z.default.bold("Files:")),a.files.forEach(r=>{t.log(` ${z.default.gray("\u2022")} ${r}`)})),a.readmeContent&&(t.newline(),t.log(z.default.bold("README:")),a.readmeContent.split(`
87
+ `).slice(0,10).forEach(c=>{t.log(` ${z.default.gray(c)}`)}),a.readmeContent.split(`
88
+ `).length>10&&t.log(` ${z.default.gray("... (truncated)")}`)),t.newline(),t.info(`Use "sinch functions init --template ${o}" to create a function from this template`)}catch(e){l.stop(),t.error(`Failed to show template details: ${e.message}`),process.exit(1)}});de.command("node").description("List Node.js templates").option("-c, --category <category>","Filter by category").action(async o=>{let e=de.commands.find(n=>n.name()==="list");e&&await e.action("node",o)});de.command("csharp").description("List C# templates").option("-c, --category <category>","Filter by category").action(async o=>{let e=de.commands.find(n=>n.name()==="list");e&&await e.action("csharp",o)});de.command("python").description("List Python templates").option("-c, --category <category>","Filter by category").action(async o=>{let e=de.commands.find(n=>n.name()==="list");e&&await e.action("python",o)});go.exports=de});var Co=F((oa,wo)=>{"use strict";var ho=require("commander"),Oe=m(require("chalk")),yo=m(require("inquirer"));D();_();T();var tt=new ho.Command("voice");tt.description("Manage Sinch Voice applications and settings");tt.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 f.load(),await Jt()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await fs(),i=e.appKey;if(!i){let s=f.getPublicCredentialInfo()?.applicationKey;s||(t.error('No default application key found. Run "sinch auth login" first.'),process.exit(1)),i=s,t.info(`Using default application: ${i}`)}if(!o){let{newUrl:s}=await yo.default.prompt([{type:"input",name:"newUrl",message:"Enter new callback URL:",validate:a=>{if(!a)return"URL is required";try{return new URL(a),!0}catch{return"Please enter a valid URL"}}}]);o=s}l.start("Updating callback URL...");try{let s=await n.voice.applications.get(i),a={...s,capability:{...s.capability,voice:{...s.capability?.voice,webhooks:{...s.capability?.voice?.webhooks,url:o,method:"POST"}}}};await n.voice.applications.update(i,a),l.succeed("Callback URL updated successfully!"),t.newline(),t.info(`Application: ${s.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(s){throw l.fail("Failed to update callback URL"),s}}catch(n){l.stop(),t.error(`Failed to update callback URL: ${n.message}`),process.exit(1)}});tt.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 f.load(),await Jt()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let e=await f.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}`,s=Buffer.from(i).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(Oe.default.gray("```bash"));let a=`curl -X GET \\
89
89
  https://calling.api.sinch.com/calling/v1/applications/${n}/callbacks/urls \\
90
- -H "Authorization: Basic ${s}"`;t.info(Pe.default.cyan(r)),t.info(Pe.default.gray("```")),t.newline()}try{let{SinchClient:o}=require("@sinch/sdk-core"),s=new o({applicationKey:e.applicationKey,applicationSecret:e.applicationSecret});d.start("Fetching callback URLs...");let r=await s.voice.applications.getCallbackURLs({applicationkey:n});d.succeed("Callback URLs retrieved"),t.newline(),t.info("\u{1F4E5} Current Callback Configuration:"),t.info(` currentCallbacks.primary: ${r?.primary||"undefined"}`),t.info(` currentCallbacks.fallback: ${r?.fallback||"undefined"}`)}catch(o){d.fail("Failed to get callback URLs"),t.error(`Error: ${o.message}`),t.newline(),t.info("Full error details:"),t.info(JSON.stringify(o,null,2))}}catch(e){t.error(`Command failed: ${e.message}`),process.exit(1)}});Je.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(i,e)=>{try{await f.load(),await At()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await f.getApplicationCredentials();n||(t.error('No application credentials found. Run "sinch auth login" first.'),process.exit(1));let o=e.appKey||n.applicationKey;t.info("\u{1F527} Updating callback URL with debug output..."),t.newline();let s=e.primaryOnly?{url:{primary:i}}:{url:{primary:i,fallback:i}},r=`${n.applicationKey}:${n.applicationSecret}`,a=Buffer.from(r).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(Pe.default.gray("```bash"));let u=`curl -X POST \\
91
- https://calling.api.sinch.com/calling/v1/applications/${o}/callbacks/urls \\
92
- -H "Authorization: Basic ${a}" \\
90
+ -H "Authorization: Basic ${s}"`;t.info(Oe.default.cyan(a)),t.info(Oe.default.gray("```")),t.newline()}try{let{SinchClient:i}=require("@sinch/sdk-core"),s=new i({applicationKey:e.applicationKey,applicationSecret:e.applicationSecret});l.start("Fetching callback URLs...");let a=await s.voice.applications.getCallbackURLs({applicationkey:n});l.succeed("Callback URLs retrieved"),t.newline(),t.info("\u{1F4E5} Current Callback Configuration:"),t.info(` currentCallbacks.primary: ${a?.primary||"undefined"}`),t.info(` currentCallbacks.fallback: ${a?.fallback||"undefined"}`)}catch(i){l.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)}});tt.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 f.load(),await Jt()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=await f.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 s=e.primaryOnly?{url:{primary:o}}:{url:{primary:o,fallback:o}},a=`${n.applicationKey}:${n.applicationSecret}`,r=Buffer.from(a).toString("base64");t.info("\u{1F4CB} CURL Command:"),t.info(Oe.default.gray("```bash"));let c=`curl -X POST \\
91
+ https://calling.api.sinch.com/calling/v1/applications/${i}/callbacks/urls \\
92
+ -H "Authorization: Basic ${r}" \\
93
93
  -H "Content-Type: application/json" \\
94
- -d '${JSON.stringify(s,null,2)}'`;t.info(Pe.default.cyan(u)),t.info(Pe.default.gray("```")),t.newline();try{let{SinchClient:c}=require("@sinch/sdk-core"),l=new c({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret});t.info("\u{1F4E4} Request Body:"),t.info(JSON.stringify(s,null,2)),t.newline(),d.start("Sending update request..."),await l.voice.applications.updateCallbackURLs({applicationkey:o,updateCallbacksRequestBody:s}),d.succeed("Update request sent"),d.start("Waiting for changes to propagate..."),await new Promise(C=>setTimeout(C,5e3)),d.start("Verifying update...");let p=await l.voice.applications.getCallbackURLs({applicationkey:o});d.succeed("Verification complete"),t.newline(),t.info("\u{1F4E5} Current Callback URLs:"),t.info(JSON.stringify(p,null,2));let m=p?.url||p?.primary||p?.urls?.primary;m===i?(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: "+i),t.info("Actual: "+(typeof m=="object"?JSON.stringify(m):m||"not found")),t.newline(),t.info("\u{1F50D} Debug - Response structure:"),t.info(" typeof currentCallbacks: "+typeof p),t.info(" currentCallbacks.url: "+(p?.url||"undefined")),t.info(" currentCallbacks.primary: "+(p?.primary||"undefined")),t.info(" currentCallbacks.urls?.primary: "+(p?.urls?.primary||"undefined")))}catch(c){d.fail("Update failed"),t.error(`Error: ${c.message}`),e.debug&&(t.newline(),t.info("Full error details:"),t.info(JSON.stringify(c,null,2)))}}catch(n){t.error(`Command failed: ${n.message}`),process.exit(1)}});async function At(){return await f.hasCredentials()}async function Ci(){return await f.createSinchClient()}Xn.exports=Je});var oo=K((tr,no)=>{"use strict";var to=require("commander"),ae=h(require("keytar")),D=h(require("chalk"));B();var Rt=h(require("inquirer")),ge="sinch-functions-cli",Ee=new to.Command("secrets");Ee.description("Manage secure secrets in OS keychain").addHelpText("after",`
94
+ -d '${JSON.stringify(s,null,2)}'`;t.info(Oe.default.cyan(c)),t.info(Oe.default.gray("```")),t.newline();try{let{SinchClient:d}=require("@sinch/sdk-core"),p=new d({applicationKey:n.applicationKey,applicationSecret:n.applicationSecret});t.info("\u{1F4E4} Request Body:"),t.info(JSON.stringify(s,null,2)),t.newline(),l.start("Sending update request..."),await p.voice.applications.updateCallbackURLs({applicationkey:i,updateCallbacksRequestBody:s}),l.succeed("Update request sent"),l.start("Waiting for changes to propagate..."),await new Promise(C=>setTimeout(C,5e3)),l.start("Verifying update...");let u=await p.voice.applications.getCallbackURLs({applicationkey:i});l.succeed("Verification complete"),t.newline(),t.info("\u{1F4E5} Current Callback URLs:"),t.info(JSON.stringify(u,null,2));let h=u?.url||u?.primary||u?.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 u),t.info(" currentCallbacks.url: "+(u?.url||"undefined")),t.info(" currentCallbacks.primary: "+(u?.primary||"undefined")),t.info(" currentCallbacks.urls?.primary: "+(u?.urls?.primary||"undefined")))}catch(d){l.fail("Update failed"),t.error(`Error: ${d.message}`),e.debug&&(t.newline(),t.info("Full error details:"),t.info(JSON.stringify(d,null,2)))}}catch(n){t.error(`Command failed: ${n.message}`),process.exit(1)}});async function Jt(){return await f.hasCredentials()}async function fs(){return await f.createSinchClient()}wo.exports=tt});var vo=F((sa,So)=>{"use strict";var bo=require("commander"),ue=m(require("keytar")),L=m(require("chalk"));_();var qt=m(require("inquirer")),we="sinch-functions-cli",De=new bo.Command("secrets");De.description("Manage secure secrets in OS keychain").addHelpText("after",`
95
95
  Examples:
96
- ${D.default.cyan("sinch secrets list")} List all custom secrets
97
- ${D.default.cyan("sinch secrets add API_KEY abc123")} Add or update a secret
98
- ${D.default.cyan("sinch secrets get API_KEY")} Get a specific secret value
99
- ${D.default.cyan("sinch secrets delete API_KEY")} Remove a secret
96
+ ${L.default.cyan("sinch secrets list")} List all custom secrets
97
+ ${L.default.cyan("sinch secrets add API_KEY abc123")} Add or update a secret
98
+ ${L.default.cyan("sinch secrets get API_KEY")} Get a specific secret value
99
+ ${L.default.cyan("sinch secrets delete API_KEY")} Remove a secret
100
100
 
101
101
  Note: Secrets are stored securely in your OS keychain:
102
102
  - Windows: Credential Manager
103
103
  - macOS: Keychain
104
104
  - Linux: Secret Service API
105
- `);Ee.command("list").description("List all custom secrets (keys only)").action(async()=>{try{let e=(await ae.default.findCredentials(ge)).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(` ${D.default.cyan("sinch secrets add <KEY> <VALUE>")}`);return}t.info(D.default.bold("Custom Secrets:")),t.info(""),e.forEach(n=>{t.info(` \u{1F510} ${D.default.cyan(n)}`)}),t.info(""),t.info(`Total: ${e.length} secret(s)`)}catch(i){t.error("Failed to list secrets:",i.message),process.exit(1)}});Ee.command("add <key> <value>").description("Add or update a secret in OS keychain").action(async(i,e)=>{try{i.match(/^[A-Z0-9_]+$/)||(t.error("Secret key must be uppercase letters, numbers, and underscores only"),t.info(`Example: ${D.default.cyan("API_KEY")}, ${D.default.cyan("DATABASE_PASSWORD")}`),process.exit(1));let n=`custom-${i}`,s=await ae.default.getPassword(ge,n)!==null;await ae.default.setPassword(ge,n,e),s?t.success(`\u2705 Updated secret: ${D.default.cyan(i)}`):t.success(`\u2705 Added secret: ${D.default.cyan(i)}`),t.info(""),t.info("\u{1F4DD} To use in your function:"),t.info(` 1. Add ${D.default.cyan(i+"=")} to your .env file (leave value empty)`),t.info(` 2. Access via ${D.default.cyan("process.env."+i)} 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)}});Ee.command("get <key>").description("Get a specific secret value").option("--show","Show the actual value (be careful!)").action(async(i,e)=>{try{let n=`custom-${i}`,o=await ae.default.getPassword(ge,n);o||(t.error(`Secret not found: ${D.default.cyan(i)}`),t.info(""),t.info("\u{1F4A1} Available secrets:"),t.info(` Run ${D.default.cyan("sinch secrets list")} to see all secrets`),process.exit(1)),t.info(`Secret: ${D.default.cyan(i)}`),e.show?(t.warn("\u26A0\uFE0F Showing secret value - be careful not to expose it!"),t.info(`Value: ${o}`)):(t.info(`Value: ${D.default.gray("[HIDDEN - use --show to reveal]")}`),t.info(`Length: ${o.length} characters`))}catch(n){t.error("Failed to get secret:",n.message),process.exit(1)}});Ee.command("delete <key>").alias("remove").alias("rm").description("Remove a secret from OS keychain").option("-f, --force","Skip confirmation").action(async(i,e)=>{try{let n=`custom-${i}`;if(await ae.default.getPassword(ge,n)||(t.error(`Secret not found: ${D.default.cyan(i)}`),process.exit(1)),!e.force&&!(await Rt.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete secret '${i}'?`,default:!1}])).confirm){t.info("Cancelled");return}await ae.default.deletePassword(ge,n)?t.success(`\u2705 Deleted secret: ${D.default.cyan(i)}`):(t.error("Failed to delete secret"),process.exit(1))}catch(n){t.error("Failed to delete secret:",n.message),process.exit(1)}});Ee.command("clear").description("Remove ALL custom secrets (use with caution!)").option("-f, --force","Skip confirmation").action(async i=>{try{let n=(await ae.default.findCredentials(ge)).filter(s=>s.account&&s.account.startsWith("custom-"));if(n.length===0){t.info("No custom secrets to clear");return}if(!i.force&&(t.warn(`\u26A0\uFE0F This will delete ${n.length} custom secret(s)`),!(await Rt.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 o=0;for(let s of n)await ae.default.deletePassword(ge,s.account)&&o++;t.success(`\u2705 Deleted ${o} custom secret(s)`)}catch(e){t.error("Failed to clear secrets:",e.message),process.exit(1)}});no.exports=Ee});var jt=require("commander"),g=h(require("chalk")),me=h(require("fs-extra")),tt=h(require("path")),Tt=h(require("os")),io=require("child_process");var we=h(require("fs")),ot=h(require("path")),it=h(require("chalk")),fo=18e5,go="https://registry.npmjs.org/@sinch/cli";function mo(){if(process.platform!=="win32")try{if(we.default.existsSync("/.dockerenv"))return!0;let i=we.default.readFileSync("/proc/1/cgroup","utf8");return i.includes("docker")||i.includes("containerd")}catch{return!1}return!!process.env.DOCKER_CONTAINER}function ho(){return!!process.env.CI}function yo(){return mo()||ho()}function wo(i){return i.includes("-dev.")?"dev":parseInt(i.split(".")[0]||"0")>=1?"latest":"beta"}function Co(i){try{if(!we.default.existsSync(i))return!0;let e=parseInt(we.default.readFileSync(i,"utf8"));return Date.now()-e>fo}catch{return!0}}function bo(i,e){let n=i.replace(/^v/,"").split("-")[0]||"0.0.0",o=e.replace(/^v/,"").split("-")[0]||"0.0.0",s=n.split(".").map(a=>parseInt(a)||0),r=o.split(".").map(a=>parseInt(a)||0);for(let a=0;a<3;a++){let u=s[a]||0,c=r[a]||0;if(c>u)return!0;if(c<u)return!1}if(i.includes("-dev.")&&e.includes("-dev.")){let a=parseInt(i.split("-dev.")[1]||"0");return parseInt(e.split("-dev.")[1]||"0")>a}return!1}async function So(i){try{let e=await fetch(go,{signal:AbortSignal.timeout(3e3)});return e.ok&&(await e.json())["dist-tags"]?.[i]||null}catch{return null}}async function vo(i,e){let n=nt().version,o=wo(n);try{let s=await So(o);if(!s)return;bo(n,s)&&(console.log(it.default.yellow(`
106
- \u{1F4E6} Update available: ${n} \u2192 ${s}`)),console.log(it.default.cyan(`Run: npm install -g @sinch/cli@${o}
107
- `))),we.default.mkdirSync(i,{recursive:!0}),we.default.writeFileSync(e,Date.now().toString())}catch{}}function _t(){if(yo())return;let i=ot.default.join(require("os").homedir(),".sinch"),e=ot.default.join(i,".last-update-check");Co(e)&&vo(i,e).catch(()=>{})}process.env.NODE_NO_WARNINGS||(process.env.NODE_NO_WARNINGS="1",process.removeAllListeners("warning"));_t();var bi=nt(),Si=Hn(),vi=zn(),$i=eo(),ki=oo(),te=new jt.Command;te.name("sinch").description("Sinch Functions - Serverless function platform for voice applications").version(bi.version,"-V, --version","output the version number").helpOption("-h, --help","Display help for command");te.addCommand(Si);te.addCommand(vi);te.addCommand($i);te.addCommand(ki);var Me=new jt.Command("auth");Me.description("Authentication management for Sinch Voice API");Me.command("login").description("Authenticate with Sinch Voice API").option("-f, --credentials-file <path>","Path to credentials JSON file").action(async i=>{let{config:e}=(j(),_(Ce)),n=require("inquirer");try{if(await e.load(),i.credentialsFile){console.log(g.default.blue(`
108
- \u{1F510} Sinch Voice API Authentication`)),console.log(g.default.gray(`Loading credentials from: ${i.credentialsFile}
109
- `)),me.default.existsSync(i.credentialsFile)||(console.error(g.default.red(`\u274C Credentials file not found: ${i.credentialsFile}`)),process.exit(1));try{let c=me.default.readFileSync(i.credentialsFile,"utf-8"),l=JSON.parse(c),m=["projectId","keyId","keySecret","applicationKey","applicationSecret"].filter(v=>!l[v]);m.length>0&&(console.error(g.default.red(`\u274C Missing required fields in credentials file: ${m.join(", ")}`)),console.error(g.default.gray(`
110
- Expected format:`)),console.error(g.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 C={projectId:l.projectId,keyId:l.keyId,keySecret:l.keySecret,applicationKey:l.applicationKey,applicationSecret:l.applicationSecret},{spinner:w}=(L(),_(Re));w.start("Verifying credentials...");try{w.update("Obtaining OAuth access token...");let{SinchAPI:v}=(U(),_(Ae)),H=await new v({apiUrl:e.get("apiUrl"),projectId:C.projectId,credentials:e._credentials}).authenticateOAuth(C.keyId,C.keySecret);w.succeed("OAuth token obtained successfully!"),w.start("Testing Voice API connection...");let{SinchClient:E}=require("@sinch/sdk-core");await new E({applicationKey:C.applicationKey,applicationSecret:C.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:C.applicationKey}),w.succeed("Credentials verified successfully!"),await e._credentials.storeOAuthToken(H),await e._credentials.store(C),console.log(g.default.green(`
105
+ `);De.command("list").description("List all custom secrets (keys only)").action(async()=>{try{let e=(await ue.default.findCredentials(we)).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(` ${L.default.cyan("sinch secrets add <KEY> <VALUE>")}`);return}t.info(L.default.bold("Custom Secrets:")),t.info(""),e.forEach(n=>{t.info(` \u{1F510} ${L.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)}});De.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: ${L.default.cyan("API_KEY")}, ${L.default.cyan("DATABASE_PASSWORD")}`),process.exit(1));let n=`custom-${o}`,s=await ue.default.getPassword(we,n)!==null;await ue.default.setPassword(we,n,e),s?t.success(`\u2705 Updated secret: ${L.default.cyan(o)}`):t.success(`\u2705 Added secret: ${L.default.cyan(o)}`),t.info(""),t.info("\u{1F4DD} To use in your function:"),t.info(` 1. Add ${L.default.cyan(o+"=")} to your .env file (leave value empty)`),t.info(` 2. Access via ${L.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)}});De.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 ue.default.getPassword(we,n);i||(t.error(`Secret not found: ${L.default.cyan(o)}`),t.info(""),t.info("\u{1F4A1} Available secrets:"),t.info(` Run ${L.default.cyan("sinch secrets list")} to see all secrets`),process.exit(1)),t.info(`Secret: ${L.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: ${L.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)}});De.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 ue.default.getPassword(we,n)||(t.error(`Secret not found: ${L.default.cyan(o)}`),process.exit(1)),!e.force&&!(await qt.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete secret '${o}'?`,default:!1}])).confirm){t.info("Cancelled");return}await ue.default.deletePassword(we,n)?t.success(`\u2705 Deleted secret: ${L.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)}});De.command("clear").description("Remove ALL custom secrets (use with caution!)").option("-f, --force","Skip confirmation").action(async o=>{try{let n=(await ue.default.findCredentials(we)).filter(s=>s.account&&s.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 qt.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 s of n)await ue.default.deletePassword(we,s.account)&&i++;t.success(`\u2705 Deleted ${i} custom secret(s)`)}catch(e){t.error("Failed to clear secrets:",e.message),process.exit(1)}});So.exports=De});var Ao={};Ke(Ao,{default:()=>gs});function Po(){return V.default.join(__dirname,"..","..","skills")}function Bt(){return V.default.join(ko.default.homedir(),".claude","skills","sinch-functions")}function Kt(){return V.default.join(process.cwd(),".claude","skills","sinch-functions")}function Vt(){return V.default.join(process.cwd(),".github","skills","sinch-functions")}function Io(o={}){let e=[],n=Bt();if(e.push({tool:"Claude Code",path:n,type:"global",installed:R.default.existsSync(V.default.join(n,"SKILL.md"))}),o.project){let i=Kt();e.push({tool:"Claude Code",path:i,type:"project",installed:R.default.existsSync(V.default.join(i,"SKILL.md"))})}if(o.project){let i=Vt();e.push({tool:"GitHub Copilot",path:i,type:"project",installed:R.default.existsSync(V.default.join(i,"SKILL.md"))})}return e}var $o,O,R,V,ko,_e,gs,Eo=re(()=>{"use strict";$o=require("commander"),O=m(require("chalk")),R=m(require("fs-extra")),V=m(require("path")),ko=m(require("os"));_();_e=new $o.Command("skills");_e.description("Manage AI coding assistant skills for Sinch development").addHelpText("after",`
106
+ Examples:
107
+ ${O.default.cyan("sinch skills install")} Install skills globally (Claude Code)
108
+ ${O.default.cyan("sinch skills install --project")} Install to current project (Claude + Copilot)
109
+ ${O.default.cyan("sinch skills install --claude")} Install for Claude Code only
110
+ ${O.default.cyan("sinch skills install --copilot")} Install for GitHub Copilot only (project)
111
+ ${O.default.cyan("sinch skills list")} Show installed skill locations
112
+ ${O.default.cyan("sinch skills uninstall")} Remove installed skills
113
+
114
+ Skills provide AI coding assistants with accurate Sinch development patterns.
115
+ `);_e.command("install").description("Install Sinch skills for AI coding assistants").option("--claude","Install for Claude Code only").option("--copilot","Install for GitHub Copilot only (requires --project)").option("--project","Install to current project (for team sharing via git)").option("--link","Symlink instead of copy (for development)").option("--force","Overwrite existing skills without prompting").action(async o=>{try{let e=Po();R.default.existsSync(e)||(t.error("Skills source not found. This may indicate a corrupted CLI installation."),t.info(`Expected path: ${e}`),process.exit(1));let n=V.default.join(e,"sinch-functions");R.default.existsSync(n)||(t.error("Skill source not found."),process.exit(1));let i=0,s=0,a=o.claude||!o.claude&&!o.copilot,r=o.copilot||!o.claude&&!o.copilot&&o.project;if(a){if(!o.project||o.claude){let c=Bt();R.default.existsSync(V.default.join(c,"SKILL.md"))&&!o.force?(t.warn(`Claude Code skill already installed at ${c}`),t.info("Use --force to overwrite"),s++):(await R.default.ensureDir(V.default.dirname(c)),o.link&&process.platform!=="win32"?(R.default.existsSync(c)&&await R.default.remove(c),await R.default.symlink(n,c,"junction"),t.success(`Linked Claude Code skill to ${c}`)):(await R.default.copy(n,c,{overwrite:!0}),t.success(`Installed Claude Code skill to ${c}`)),i++)}if(o.project){let c=Kt();R.default.existsSync(V.default.join(c,"SKILL.md"))&&!o.force?(t.warn(`Claude Code project skill already installed at ${c}`),t.info("Use --force to overwrite"),s++):(await R.default.ensureDir(V.default.dirname(c)),await R.default.copy(n,c,{overwrite:!0}),t.success(`Installed Claude Code skill to ${c}`),i++)}}if(r&&o.project){let c=Vt();R.default.existsSync(V.default.join(c,"SKILL.md"))&&!o.force?(t.warn(`Copilot skill already installed at ${c}`),t.info("Use --force to overwrite"),s++):(await R.default.ensureDir(V.default.dirname(c)),await R.default.copy(n,c,{overwrite:!0}),t.success(`Installed Copilot skill to ${c}`),i++)}else o.copilot&&!o.project&&(t.warn("Copilot requires --project flag (no global installation supported)"),t.info("Use: sinch skills install --copilot --project"));t.info(""),i>0&&t.success(`Installed ${i} skill(s)`),s>0&&t.info(`Skipped ${s} existing skill(s)`),i>0&&(t.info(""),t.info(O.default.bold("Next steps:")),a&&(t.info(` ${O.default.cyan("\u2022")} Claude Code will now have Sinch expertise`),t.info(` ${O.default.cyan("\u2022")} Ask about voice IVRs, SVAML, or CLI commands`)),r&&o.project&&(t.info(` ${O.default.cyan("\u2022")} Copilot will use Sinch patterns for code suggestions`),t.info(` ${O.default.cyan("\u2022")} Commit .github/skills/ to share with team`)))}catch(e){t.error("Failed to install skills:",e.message),process.exit(1)}});_e.command("list").description("Show installed skill locations").action(async()=>{try{let o=Io({project:!0}),e=o.filter(r=>r.type==="global"),n=o.filter(r=>r.type==="project");t.info(O.default.bold(`Sinch Skills Installation Status
116
+ `)),t.info(O.default.underline("Global (personal machine):"));let i=!1;for(let r of e)r.installed?(t.info(` ${O.default.green("\u2713")} ${r.tool}: ${O.default.gray(r.path)}`),i=!0):t.info(` ${O.default.gray("\u25CB")} ${r.tool}: ${O.default.gray("not installed")}`);i||t.info(` ${O.default.gray("No global skills installed")}`),t.info(""),t.info(O.default.underline("Project (current directory):"));let s=!1;for(let r of n)r.installed?(t.info(` ${O.default.green("\u2713")} ${r.tool}: ${O.default.gray(r.path)}`),s=!0):t.info(` ${O.default.gray("\u25CB")} ${r.tool}: ${O.default.gray("not installed")}`);s||t.info(` ${O.default.gray("No project skills installed")}`),t.info(""),o.some(r=>r.installed)||(t.info("Run `sinch skills install` to install skills globally"),t.info("Run `sinch skills install --project` to install for this project"))}catch(o){t.error("Failed to list skills:",o.message),process.exit(1)}});_e.command("uninstall").description("Remove installed Sinch skills").option("--claude","Uninstall from Claude Code only").option("--copilot","Uninstall from GitHub Copilot only").option("--project","Uninstall from current project only").option("--all","Uninstall from all locations").action(async o=>{try{let e=0,n=!o.claude&&!o.copilot&&!o.project&&!o.all,i=o.all||n,s=o.project&&!o.all&&!n,a=o.claude||i||s,r=o.copilot||i||s;if(a){if(!s){let c=Bt();R.default.existsSync(c)&&(await R.default.remove(c),t.success(`Removed Claude Code skill from ${c}`),e++)}if(s||i){let c=Kt();R.default.existsSync(c)&&(await R.default.remove(c),t.success(`Removed Claude Code skill from ${c}`),e++)}}if(r&&(s||i)){let c=Vt();R.default.existsSync(c)&&(await R.default.remove(c),t.success(`Removed Copilot skill from ${c}`),e++)}t.info(""),e>0?t.success(`Removed ${e} skill(s)`):t.info("No skills found to remove")}catch(e){t.error("Failed to uninstall skills:",e.message),process.exit(1)}});_e.command("update").description("Update skills to latest version").option("--project","Update project skills as well").action(async o=>{try{t.info(`Updating Sinch skills...
117
+ `);let n=Io({project:o.project}).filter(r=>r.installed);if(n.length===0){t.info("No skills installed. Run `sinch skills install` first.");return}let i=Po(),s=V.default.join(i,"sinch-functions"),a=0;for(let r of n)await R.default.copy(s,r.path,{overwrite:!0}),t.success(`Updated ${r.tool} (${r.type})`),a++;t.info(""),t.success(`Updated ${a} skill(s)`)}catch(e){t.error("Failed to update skills:",e.message),process.exit(1)}});module.exports=_e;gs=_e});async function ms(){await f.load(),await f.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1))}async function E(){return await ms(),await f.createSinchClient()}function ft(o){let e=o||f.get("conversation-app-id");return e||(t.error("No Conversation App ID configured."),t.info("Set default: sinch config set conversation-app-id <id>"),t.info("Or specify: --app <app-id>"),process.exit(1)),e}var Te=re(()=>{"use strict";D();_()});var _o=F((fa,Do)=>{"use strict";var jo=require("commander"),Ro=m(require("inquirer"));_();T();Te();var Oo=new jo.Command("send");Oo.description("Send a message via Conversation API").argument("[recipient]","Recipient phone number (e.g., +15551234567)").argument("[message]","Message text to send").option("-c, --channel <channel>","Channel (SMS, WHATSAPP, MESSENGER, etc.)","SMS").option("-a, --app <app-id>","Conversation App ID (uses default if configured)").option("-m, --media <url>","Media URL for media messages").option("--caption <text>","Caption for media messages").option("-t, --template <name>","Template name for template messages").option("-p, --params <json>","Template parameters as JSON string").option("--location","Send location message").option("--lat <latitude>","Latitude for location messages",parseFloat).option("--lng <longitude>","Longitude for location messages",parseFloat).option("-n, --name <name>","Location name").option("--json","Output result as JSON").action(async(o,e,n)=>{try{let i=await E();if(!o||!e&&!n?.media&&!n?.template&&!n?.location){let a=await Ro.default.prompt([{type:"input",name:"recipient",message:"Enter recipient phone number:",when:!o,validate:r=>r?r.startsWith("+")?!0:"Phone number must start with +":"Recipient is required"},{type:"input",name:"message",message:"Enter message:",when:!e&&!n?.media&&!n?.template&&!n?.location,validate:r=>r?!0:"Message is required"},{type:"list",name:"channel",message:"Select channel:",choices:["SMS","WHATSAPP","MESSENGER","INSTAGRAM","VIBER","TELEGRAM","RCS","LINE"],default:n?.channel||"SMS",when:!n?.channel}]);o=o||a.recipient,e=e||a.message,a.channel&&(n={...n,channel:a.channel})}let s=ft(n?.app);l.start("Sending message...");try{let a;if(n?.location)(!n.lat||!n.lng)&&(l.fail("Location messages require --lat and --lng"),process.exit(1)),a=await i.conversation.messages.send({app_id:s,recipient:{identified_by:{channel_identities:[{channel:n.channel||"SMS",identity:o}]}},location_message:{coordinates:{latitude:n.lat,longitude:n.lng},title:n.name}});else if(n?.template){let r=n.params?JSON.parse(n.params):{};a=await i.conversation.messages.send({app_id:s,recipient:{identified_by:{channel_identities:[{channel:n.channel||"WHATSAPP",identity:o}]}},template_message:{template_reference:{template_id:n.template,version:r.version||"1"},parameters:r}})}else n?.media?a=await i.conversation.messages.send({app_id:s,recipient:{identified_by:{channel_identities:[{channel:n.channel||"WHATSAPP",identity:o}]}},media_message:{url:n.media,caption:n.caption}}):a=await i.conversation.messages.send({app_id:s,recipient:{identified_by:{channel_identities:[{channel:n?.channel||"SMS",identity:o}]}},text_message:{text:e}});l.succeed("Message sent successfully!"),n?.json?console.log(JSON.stringify(a,null,2)):(t.newline(),t.info(`Message ID: ${a.message_id}`),t.info(`Recipient: ${o}`),t.info(`Channel: ${n?.channel||"SMS"}`))}catch(a){l.fail("Failed to send message"),a.message?.includes("WHATSAPP")||a.message?.includes("channel not configured")?(t.error(`Error: WhatsApp channel not configured for app '${s}'`),t.newline(),t.info("To use WhatsApp, configure WhatsApp credentials in your Conversation app:"),t.info(" 1. Visit https://dashboard.sinch.com/convapi/apps"),t.info(" 2. Add WhatsApp channel credentials"),t.info(" 3. Verify your WhatsApp Business Account"),t.newline(),t.info("Or use SMS (no additional setup required):"),t.info(` sinch conversation send ${o} "${e}"`)):t.error(`Error: ${a.message}`),process.exit(1)}}catch(i){l.stop(),t.error(`Failed to send message: ${i.message}`),process.exit(1)}});Do.exports=Oo});var Fo=F((ya,No)=>{"use strict";var To=require("commander");_();T();Te();var nt=new To.Command("messages");nt.description("Manage conversation messages");nt.command("get").description("Get a specific message by ID").argument("<message-id>","Message ID to retrieve").option("--json","Output result as JSON").action(async(o,e)=>{try{let n=await E();l.start("Fetching message...");let i=await n.conversation.messages.get({message_id:o});l.succeed("Message retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`Message ID: ${i.id}`),t.info(`Direction: ${i.direction}`),t.info(`Channel: ${i.channel_identity?.channel||"N/A"}`),t.info(`Contact ID: ${i.contact_id||"N/A"}`),t.info(`Conversation ID: ${i.conversation_id||"N/A"}`),t.info(`Status: ${i.accept_time?"Accepted":"Pending"}`),i.text_message&&t.info(`Text: ${i.text_message.text}`),i.media_message&&t.info(`Media URL: ${i.media_message.url}`))}catch(n){l.stop(),t.error(`Failed to get message: ${n.message}`),process.exit(1)}});nt.command("list").description("List messages").option("-c, --channel <channel>","Filter by channel").option("-l, --limit <number>","Limit number of results",parseInt,20).option("--json","Output result as JSON").action(async o=>{try{let e=await E();l.start("Fetching messages...");let n=await e.conversation.messages.list({page_size:o.limit||20,...o.channel&&{channel:o.channel}});l.succeed(`Retrieved ${n.messages?.length||0} messages`),o.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.messages&&n.messages.length>0?n.messages.forEach(i=>{t.info(`[${i.id}] ${i.direction} via ${i.channel_identity?.channel||"N/A"}`),i.text_message&&t.info(` "${i.text_message.text}"`),t.newline()}):t.info("No messages found"))}catch(e){l.stop(),t.error(`Failed to list messages: ${e.message}`),process.exit(1)}});nt.command("delete").description("Delete a message").argument("<message-id>","Message ID to delete").action(async o=>{try{let e=await E();l.start("Deleting message..."),await e.conversation.messages.delete({message_id:o}),l.succeed("Message deleted successfully")}catch(e){l.stop(),t.error(`Failed to delete message: ${e.message}`),process.exit(1)}});No.exports=nt});var Mo=F((Sa,Uo)=>{"use strict";var xo=require("commander"),Lo=m(require("inquirer"));_();T();Te();var Ce=new xo.Command("contacts");Ce.description("Manage conversation contacts");Ce.command("create").description("Create a new contact").option("-p, --phone <number>","Phone number").option("-e, --email <email>","Email address").option("-n, --name <name>","Contact name").option("-d, --display-name <name>","Display name").option("--json","Output result as JSON").action(async o=>{try{if(!o.phone&&!o.email){let i=await Lo.default.prompt([{type:"input",name:"phone",message:"Enter phone number (optional):",validate:s=>s&&!s.startsWith("+")?"Phone number must start with +":!0},{type:"input",name:"email",message:"Enter email address (optional):"},{type:"input",name:"name",message:"Enter contact name (optional):"}]);o={...o,...i}}!o.phone&&!o.email&&(t.error("At least one of phone or email is required"),process.exit(1));let e=await E();l.start("Creating contact...");let n=await e.conversation.contact.create({channel_identities:[...o.phone?[{channel:"SMS",identity:o.phone}]:[],...o.email?[{channel:"EMAIL",identity:o.email}]:[]],display_name:o.displayName||o.name,...o.name&&{metadata:JSON.stringify({name:o.name})}});l.succeed("Contact created successfully!"),o.json?console.log(JSON.stringify(n,null,2)):(t.newline(),t.info(`Contact ID: ${n.id}`),t.info(`Display Name: ${n.display_name||"N/A"}`),o.phone&&t.info(`Phone: ${o.phone}`),o.email&&t.info(`Email: ${o.email}`))}catch(e){l.stop(),t.error(`Failed to create contact: ${e.message}`),process.exit(1)}});Ce.command("get").description("Get a specific contact by ID").argument("<contact-id>","Contact ID to retrieve").option("--json","Output result as JSON").action(async(o,e)=>{try{let n=await E();l.start("Fetching contact...");let i=await n.conversation.contact.get({contact_id:o});l.succeed("Contact retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`Contact ID: ${i.id}`),t.info(`Display Name: ${i.display_name||"N/A"}`),t.info(`Language: ${i.language||"N/A"}`),i.channel_identities&&i.channel_identities.length>0&&(t.newline(),t.info("Channel Identities:"),i.channel_identities.forEach(s=>{t.info(` ${s.channel}: ${s.identity}`)})))}catch(n){l.stop(),t.error(`Failed to get contact: ${n.message}`),process.exit(1)}});Ce.command("list").description("List contacts").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async o=>{try{let e=await E();l.start("Fetching contacts...");let n=await e.conversation.contact.list({page_size:o.limit||50});l.succeed(`Retrieved ${n.contacts?.length||0} contacts`),o.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.contacts&&n.contacts.length>0?n.contacts.forEach(i=>{t.info(`[${i.id}] ${i.display_name||"No name"}`),i.channel_identities&&i.channel_identities.length>0&&i.channel_identities.forEach(s=>{t.info(` ${s.channel}: ${s.identity}`)}),t.newline()}):t.info("No contacts found"))}catch(e){l.stop(),t.error(`Failed to list contacts: ${e.message}`),process.exit(1)}});Ce.command("update").description("Update a contact").argument("<contact-id>","Contact ID to update").option("-n, --name <name>","New contact name").option("-d, --display-name <name>","New display name").option("--json","Output result as JSON").action(async(o,e)=>{try{!e.displayName&&!e.name&&(t.error("At least one update field is required (--name or --display-name)"),process.exit(1));let n=await E();l.start("Updating contact...");let i=await n.conversation.contact.update({contact_id:o,display_name:e.displayName||e.name,...e.name&&{metadata:JSON.stringify({name:e.name})}});l.succeed("Contact updated successfully!"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`Contact ID: ${i.id}`),t.info(`Display Name: ${i.display_name||"N/A"}`))}catch(n){l.stop(),t.error(`Failed to update contact: ${n.message}`),process.exit(1)}});Ce.command("delete").description("Delete a contact").argument("<contact-id>","Contact ID to delete").action(async o=>{try{let e=await E();l.start("Deleting contact..."),await e.conversation.contact.delete({contact_id:o}),l.succeed("Contact deleted successfully")}catch(e){l.stop(),t.error(`Failed to delete contact: ${e.message}`),process.exit(1)}});Ce.command("merge").description("Merge two contacts").argument("<source-id>","Source contact ID (will be merged into destination)").argument("<dest-id>","Destination contact ID").option("--json","Output result as JSON").action(async(o,e,n)=>{try{let i=await E();l.start("Merging contacts...");let s=await i.conversation.contact.mergeContact({destination_id:e,source_id:o});l.succeed("Contacts merged successfully!"),n.json?console.log(JSON.stringify(s,null,2)):(t.newline(),t.info(`Source contact ${o} merged into ${e}`),t.info(`Result Contact ID: ${s.id}`))}catch(i){l.stop(),t.error(`Failed to merge contacts: ${i.message}`),process.exit(1)}});Uo.exports=Ce});var Bo=F((Pa,qo)=>{"use strict";var Jo=require("commander");_();T();Te();var ot=new Jo.Command("conversations");ot.description("Manage conversations");ot.command("list").description("List conversations").option("-a, --app <app-id>","Filter by Conversation App ID").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async o=>{try{let e=await E();l.start("Fetching conversations...");let n=await e.conversation.conversation.list({page_size:o.limit||50,...o.app&&{app_id:o.app}});l.succeed(`Retrieved ${n.conversations?.length||0} conversations`),o.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.conversations&&n.conversations.length>0?n.conversations.forEach(i=>{t.info(`[${i.id}]`),t.info(` App ID: ${i.app_id}`),t.info(` Active: ${i.active_channel||"N/A"}`),t.info(` Last Updated: ${i.last_received?new Date(i.last_received).toLocaleString():"N/A"}`),t.newline()}):t.info("No conversations found"))}catch(e){l.stop(),t.error(`Failed to list conversations: ${e.message}`),process.exit(1)}});ot.command("get").description("Get a specific conversation by ID").argument("<conversation-id>","Conversation ID to retrieve").option("--json","Output result as JSON").action(async(o,e)=>{try{let n=await E();l.start("Fetching conversation...");let i=await n.conversation.conversation.get({conversation_id:o});l.succeed("Conversation retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`Conversation ID: ${i.id}`),t.info(`App ID: ${i.app_id}`),t.info(`Active Channel: ${i.active_channel||"N/A"}`),t.info(`Contact ID: ${i.contact_id||"N/A"}`),i.metadata&&(t.newline(),t.info("Metadata:"),t.info(JSON.stringify(i.metadata,null,2))))}catch(n){l.stop(),t.error(`Failed to get conversation: ${n.message}`),process.exit(1)}});ot.command("stop").description("Stop an active conversation").argument("<conversation-id>","Conversation ID to stop").action(async o=>{try{let e=await E();l.start("Stopping conversation..."),await e.conversation.conversation.delete({conversation_id:o}),l.succeed("Conversation stopped successfully")}catch(e){l.stop(),t.error(`Failed to stop conversation: ${e.message}`),process.exit(1)}});qo.exports=ot});var Wo=F((ja,Vo)=>{"use strict";var Ko=require("commander"),Wt=m(require("inquirer"));_();T();Te();var Je=new Ko.Command("apps");Je.description("Manage Conversation apps");Je.command("list").description("List Conversation apps").option("-l, --limit <number>","Limit number of results",parseInt,50).option("--json","Output result as JSON").action(async o=>{try{let e=await E();l.start("Fetching apps...");let n=await e.conversation.app.list({page_size:o.limit||50});l.succeed(`Retrieved ${n.apps?.length||0} apps`),o.json?console.log(JSON.stringify(n,null,2)):(t.newline(),n.apps&&n.apps.length>0?n.apps.forEach(i=>{t.info(`[${i.id}] ${i.display_name||"No name"}`),t.info(` Channels: ${i.channel_credentials?.length||0} configured`),t.newline()}):t.info("No apps found"))}catch(e){l.stop(),t.error(`Failed to list apps: ${e.message}`),process.exit(1)}});Je.command("get").description("Get a specific Conversation app by ID").argument("<app-id>","App ID to retrieve").option("--json","Output result as JSON").action(async(o,e)=>{try{let n=await E();l.start("Fetching app...");let i=await n.conversation.app.get({app_id:o});l.succeed("App retrieved"),e.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`App ID: ${i.id}`),t.info(`Display Name: ${i.display_name||"N/A"}`),t.info("Rate Limits:",i.rate_limits||"N/A"),i.channel_credentials&&i.channel_credentials.length>0&&(t.newline(),t.info("Configured Channels:"),i.channel_credentials.forEach(s=>{t.info(` - ${s.channel}`)})),i.conversation_metadata_report_view&&(t.newline(),t.info(`Metadata Report: ${i.conversation_metadata_report_view}`)))}catch(n){l.stop(),t.error(`Failed to get app: ${n.message}`),process.exit(1)}});Je.command("create").description("Create a new Conversation app").argument("[name]","App display name").option("--json","Output result as JSON").action(async(o,e)=>{try{o||(o=(await Wt.default.prompt([{type:"input",name:"name",message:"Enter app display name:",validate:a=>a?!0:"App name is required"}])).name);let n=await E();l.start("Creating app...");let i=await n.conversation.app.create({display_name:o});l.succeed("App created successfully!"),e?.json?console.log(JSON.stringify(i,null,2)):(t.newline(),t.info(`App ID: ${i.id}`),t.info(`Display Name: ${i.display_name}`),t.newline(),t.info("\u{1F4A1} Set as default: sinch config set conversation-app-id "+i.id))}catch(n){l.stop(),t.error(`Failed to create app: ${n.message}`),process.exit(1)}});Je.command("delete").description("Delete a Conversation app").argument("<app-id>","App ID to delete").action(async o=>{try{let{confirm:e}=await Wt.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete app ${o}?`,default:!1}]);if(!e){t.info("Deletion cancelled");return}let n=await E();l.start("Deleting app..."),await n.conversation.app.delete({app_id:o}),l.succeed("App deleted successfully")}catch(e){l.stop(),t.error(`Failed to delete app: ${e.message}`),process.exit(1)}});Vo.exports=Je});var Yo=F((Ta,Ho)=>{"use strict";var Go=require("commander"),Gt=m(require("inquirer"));D();_();T();Te();var qe=new Go.Command("webhooks");qe.description("Manage webhooks for Conversation apps");qe.command("list").description("List webhooks for a Conversation app").option("-a, --app <app-id>","Conversation App ID").option("--json","Output result as JSON").action(async o=>{try{let e=ft(o.app),n=await E();l.start("Fetching webhooks...");let i=await n.conversation.webhooks.list({app_id:e});l.succeed(`Retrieved ${i.webhooks?.length||0} webhooks`),o.json?console.log(JSON.stringify(i,null,2)):(t.newline(),i.webhooks&&i.webhooks.length>0?i.webhooks.forEach(s=>{t.info(`[${s.id}]`),t.info(` URL: ${s.target}`),t.info(` Triggers: ${s.triggers?.join(", ")||"N/A"}`),t.info(` Secret: ${s.secret?"********":"Not set"}`),t.newline()}):t.info("No webhooks found for this app"))}catch(e){l.stop(),t.error(`Failed to list webhooks: ${e.message}`),process.exit(1)}});qe.command("create").description("Create a new webhook for a Conversation app").option("-a, --app <app-id>","Conversation App ID").option("-u, --url <url>","Webhook URL").option("-t, --triggers <triggers>","Comma-separated list of triggers (e.g., MESSAGE_INBOUND,MESSAGE_DELIVERY)").option("-s, --secret <secret>","Webhook secret for signature validation").option("--json","Output result as JSON").action(async o=>{try{await f.load(),await f.hasCredentials()||(t.error('Not authenticated. Run "sinch auth login" first.'),process.exit(1));let n=o.app;if(!n){let r=f.get("conversation-app-id");r&&(n=r,t.info(`Using default app: ${n}`))}if(!n||!o.url||!o.triggers){let r=await Gt.default.prompt([{type:"input",name:"appId",message:"Enter Conversation App ID:",when:!n,validate:c=>c?!0:"App ID is required"},{type:"input",name:"url",message:"Enter webhook URL:",when:!o.url,validate:c=>{if(!c)return"URL is required";try{return new URL(c),!0}catch{return"Please enter a valid URL"}}},{type:"checkbox",name:"triggers",message:"Select webhook triggers:",when:!o.triggers,choices:["MESSAGE_INBOUND","MESSAGE_DELIVERY","MESSAGE_SUBMIT","EVENT_INBOUND","CONVERSATION_START","CONVERSATION_STOP","CONTACT_CREATE","CONTACT_DELETE","CONTACT_MERGE","CONTACT_UPDATE"],validate:c=>c.length>0?!0:"Select at least one trigger"},{type:"input",name:"secret",message:"Enter webhook secret (optional, press enter to skip):"}]);n=n||r.appId,o.url=o.url||r.url,o.triggers=o.triggers||r.triggers.join(","),o.secret=o.secret||r.secret}let i=await E(),s=o.triggers.split(",").map(r=>r.trim());l.start("Creating webhook...");let a=await i.conversation.webhooks.create({app_id:n,target:o.url,triggers:s,...o.secret&&{secret:o.secret}});l.succeed("Webhook created successfully!"),o.json?console.log(JSON.stringify(a,null,2)):(t.newline(),t.info(`Webhook ID: ${a.id}`),t.info(`URL: ${a.target}`),t.info(`Triggers: ${a.triggers?.join(", ")}`),o.secret&&t.info("Secret: ********"))}catch(e){l.stop(),t.error(`Failed to create webhook: ${e.message}`),process.exit(1)}});qe.command("update").description("Update a webhook").argument("<webhook-id>","Webhook ID to update").option("-u, --url <url>","New webhook URL").option("-t, --triggers <triggers>","New comma-separated list of triggers").option("-s, --secret <secret>","New webhook secret").option("--json","Output result as JSON").action(async(o,e)=>{try{!e.url&&!e.triggers&&!e.secret&&(t.error("At least one update field is required (--url, --triggers, or --secret)"),process.exit(1));let n=await E(),i={};e.url&&(i.target=e.url),e.triggers&&(i.triggers=e.triggers.split(",").map(a=>a.trim())),e.secret&&(i.secret=e.secret),l.start("Updating webhook...");let s=await n.conversation.webhooks.update({webhook_id:o,...i});l.succeed("Webhook updated successfully!"),e.json?console.log(JSON.stringify(s,null,2)):(t.newline(),t.info(`Webhook ID: ${s.id}`),t.info(`URL: ${s.target}`),t.info(`Triggers: ${s.triggers?.join(", ")}`))}catch(n){l.stop(),t.error(`Failed to update webhook: ${n.message}`),process.exit(1)}});qe.command("delete").description("Delete a webhook").argument("<webhook-id>","Webhook ID to delete").action(async o=>{try{let{confirm:e}=await Gt.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to delete webhook ${o}?`,default:!1}]);if(!e){t.info("Deletion cancelled");return}let n=await E();l.start("Deleting webhook..."),await n.conversation.webhooks.delete({webhook_id:o}),l.succeed("Webhook deleted successfully")}catch(e){l.stop(),t.error(`Failed to delete webhook: ${e.message}`),process.exit(1)}});Ho.exports=qe});var Zo=F((Na,Qo)=>{"use strict";var zo=require("commander"),hs=_o(),ys=Fo(),ws=Mo(),Cs=Bo(),bs=Wo(),Ss=Yo(),be=new zo.Command("conversation");be.description("Manage Sinch Conversations API");be.addCommand(hs);be.addCommand(ys);be.addCommand(ws);be.addCommand(Cs);be.addCommand(bs);be.addCommand(Ss);Qo.exports=be});var Ht=require("commander"),g=m(require("chalk")),Se=m(require("fs-extra")),gt=m(require("path")),Yt=m(require("os")),Xo=require("child_process");var ke=m(require("fs")),ht=m(require("path")),yt=m(require("chalk")),ai=18e5,ci="https://registry.npmjs.org/@sinch/cli";function li(){if(process.platform!=="win32")try{if(ke.default.existsSync("/.dockerenv"))return!0;let o=ke.default.readFileSync("/proc/1/cgroup","utf8");return o.includes("docker")||o.includes("containerd")}catch{return!1}return!!process.env.DOCKER_CONTAINER}function di(){return!!process.env.CI}function pi(){return li()||di()}function ui(o){return o.includes("-dev.")?"dev":parseInt(o.split(".")[0]||"0")>=1?"latest":"beta"}function fi(o){try{if(!ke.default.existsSync(o))return!0;let e=parseInt(ke.default.readFileSync(o,"utf8"));return Date.now()-e>ai}catch{return!0}}function gi(o,e){let n=o.replace(/^v/,"").split("-")[0]||"0.0.0",i=e.replace(/^v/,"").split("-")[0]||"0.0.0",s=n.split(".").map(r=>parseInt(r)||0),a=i.split(".").map(r=>parseInt(r)||0);for(let r=0;r<3;r++){let c=s[r]||0,d=a[r]||0;if(d>c)return!0;if(d<c)return!1}if(o.includes("-dev.")&&e.includes("-dev.")){let r=parseInt(o.split("-dev.")[1]||"0");return parseInt(e.split("-dev.")[1]||"0")>r}return!1}async function mi(o){try{let e=await fetch(ci,{signal:AbortSignal.timeout(3e3)});return e.ok&&(await e.json())["dist-tags"]?.[o]||null}catch{return null}}async function hi(o,e){let n=mt().version,i=ui(n);try{let s=await mi(i);if(!s)return;gi(n,s)&&(console.log(yt.default.yellow(`
118
+ \u{1F4E6} Update available: ${n} \u2192 ${s}`)),console.log(yt.default.cyan(`Run: npm install -g @sinch/cli@${i}
119
+ `))),ke.default.mkdirSync(o,{recursive:!0}),ke.default.writeFileSync(e,Date.now().toString())}catch{}}function Xt(){if(pi())return;let o=ht.default.join(require("os").homedir(),".sinch"),e=ht.default.join(o,".last-update-check");fi(e)&&hi(o,e).catch(()=>{})}process.env.NODE_NO_WARNINGS||(process.env.NODE_NO_WARNINGS="1",process.removeAllListeners("warning"));Xt();var vs=mt(),$s=uo(),ks=mo(),Ps=Co(),Is=vo(),As=(Eo(),M(Ao)),Es=Zo(),Q=new Ht.Command;Q.name("sinch").description("Sinch Functions - Serverless function platform for voice applications").version(vs.version,"-V, --version","output the version number").helpOption("-h, --help","Display help for command");Q.addCommand($s);Q.addCommand(ks);Q.addCommand(Ps);Q.addCommand(Is);Q.addCommand(As);Q.addCommand(Es);var it=new Ht.Command("auth");it.description("Authentication management for Sinch Voice API");it.command("login").description("Authenticate with Sinch Voice API").option("-f, --credentials-file <path>","Path to credentials JSON file").action(async o=>{let{config:e}=(D(),M(Pe)),n=require("inquirer");try{if(await e.load(),o.credentialsFile){console.log(g.default.blue(`
120
+ \u{1F510} Sinch Voice API Authentication`)),console.log(g.default.gray(`Loading credentials from: ${o.credentialsFile}
121
+ `)),Se.default.existsSync(o.credentialsFile)||(console.error(g.default.red(`\u274C Credentials file not found: ${o.credentialsFile}`)),process.exit(1));try{let d=Se.default.readFileSync(o.credentialsFile,"utf-8"),p=JSON.parse(d),h=["projectId","keyId","keySecret","applicationKey","applicationSecret"].filter(v=>!p[v]);h.length>0&&(console.error(g.default.red(`\u274C Missing required fields in credentials file: ${h.join(", ")}`)),console.error(g.default.gray(`
122
+ Expected format:`)),console.error(g.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 C={projectId:p.projectId,keyId:p.keyId,keySecret:p.keySecret,applicationKey:p.applicationKey,applicationSecret:p.applicationSecret},{spinner:w}=(T(),M(xe));w.start("Verifying credentials...");try{w.update("Obtaining OAuth access token...");let{SinchAPI:v}=(K(),M(Fe)),Z=await new v({apiUrl:e.get("apiUrl"),projectId:C.projectId,credentials:e._credentials}).authenticateOAuth(C.keyId,C.keySecret);w.succeed("OAuth token obtained successfully!"),w.start("Testing Voice API connection...");let{SinchClient:I}=require("@sinch/sdk-core");await new I({applicationKey:C.applicationKey,applicationSecret:C.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:C.applicationKey}),w.succeed("Credentials verified successfully!"),await e._credentials.storeOAuthToken(Z),await e._credentials.store(C),console.log(g.default.green(`
111
123
  \u2705 Authentication successful!`)),console.log(g.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(g.default.blue("\u{1F512} Security:")),console.log(g.default.gray(" \u2022 Secrets stored in OS credential manager (Windows/macOS/Linux)")),console.log(g.default.gray(" \u2022 Non-sensitive data in ~/.sinch/config.json"));return}catch(v){w.fail(g.default.red("Authentication failed")),console.error(g.default.red(`
112
- \u274C ${v.message||"Failed to authenticate with provided credentials"}`)),process.exit(1)}}catch(c){console.error(g.default.red(`\u274C Failed to parse credentials file: ${c.message}`)),process.exit(1)}}let o=await e.getCredentials(),s=e.getPublicCredentialInfo();console.log(g.default.blue(`
113
- \u{1F510} Sinch Voice API Authentication`)),console.log(o?g.default.gray(`Found existing credentials. Press Enter to reuse them or enter new values.
124
+ \u274C ${v.message||"Failed to authenticate with provided credentials"}`)),process.exit(1)}}catch(d){console.error(g.default.red(`\u274C Failed to parse credentials file: ${d.message}`)),process.exit(1)}}let i=await e.getCredentials(),s=e.getPublicCredentialInfo();console.log(g.default.blue(`
125
+ \u{1F510} Sinch Voice API Authentication`)),console.log(i?g.default.gray(`Found existing credentials. Press Enter to reuse them or enter new values.
114
126
  `):g.default.gray(`Enter your Sinch credentials to manage voice applications and callbacks
115
- `));let r=await n.prompt([{type:"input",name:"projectId",message:"Project ID (from Sinch Dashboard):",default:s?.projectId||void 0,validate:c=>!c&&s?.projectId?!0:c.length>0||"Project ID is required"},{type:"input",name:"keyId",message:"Key ID (from Project \u2192 Access Keys):",default:s?.keyId||void 0,validate:c=>!c&&s?.keyId?!0:c.length>0||"Key ID is required"},{type:"password",name:"keySecret",message:"Key Secret:",default:o?.keySecret||void 0,validate:c=>!c&&o?.keySecret?!0:c.length>0||"Key Secret is required"},{type:"input",name:"applicationKey",message:"Voice Application Key:",default:s?.applicationKey||void 0,validate:c=>!c&&s?.applicationKey?!0:c.length>0||"Application Key is required"},{type:"password",name:"applicationSecret",message:"Voice Application Secret:",default:o?.applicationSecret||void 0,validate:c=>!c&&o?.applicationSecret?!0:c.length>0||"Application Secret is required"}]),a={projectId:r.projectId||s?.projectId,keyId:r.keyId||s?.keyId,keySecret:r.keySecret||o?.keySecret,applicationKey:r.applicationKey||s?.applicationKey,applicationSecret:r.applicationSecret||o?.applicationSecret},{spinner:u}=(L(),_(Re));u.start("Verifying credentials...");try{u.update("Obtaining OAuth access token...");let{SinchAPI:c}=(U(),_(Ae)),p=await new c({apiUrl:e.get("apiUrl"),projectId:a.projectId||e.get("projectId"),credentials:e._credentials}).authenticateOAuth(a.keyId,a.keySecret);u.succeed("OAuth token obtained successfully!"),u.start("Testing Voice API connection...");let{SinchClient:m}=require("@sinch/sdk-core");await new m({applicationKey:a.applicationKey,applicationSecret:a.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:a.applicationKey}),u.succeed("Credentials verified successfully!"),await e._credentials.storeOAuthToken(p),await e._credentials.store(a),console.log(g.default.green(`
116
- \u2705 Authentication successful!`)),console.log(g.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(g.default.blue("\u{1F512} Security:")),console.log(g.default.gray(" \u2022 Secrets stored in OS credential manager (Windows/macOS/Linux)")),console.log(g.default.gray(" \u2022 Non-sensitive data in ~/.sinch/config.json"))}catch(c){u.fail("Authentication failed"),console.error(g.default.red(`
117
- \u274C Error: ${c.message}`)),console.log(g.default.yellow(`
118
- \u{1F4A1} Please check your credentials and try again`)),process.exit(1)}}catch(o){console.error(g.default.red(`Authentication failed: ${o.message}`)),process.exit(1)}});Me.command("status").description("Show current authentication status").action(async()=>{let{config:i}=(j(),_(Ce));try{await i.load();let e=await i.hasCredentials(),n=i.getPublicCredentialInfo();if(console.log(g.default.blue(`
119
- \u{1F510} Authentication Status`)),e&&n){console.log(g.default.green("\u2705 Authenticated")),console.log(` Project ID: ${n.projectId}`),console.log(` Key ID: ${n.keyId}`),console.log(` Application Key: ${n.applicationKey}`),console.log(g.default.gray(" (Secrets stored securely in OS keychain)"));try{let s=(U(),_(Ae)).default,r=i.getApiConfig();await new s(r).authenticate(),console.log(g.default.green(" OAuth Token: Valid"))}catch{console.log(g.default.yellow(" OAuth Token: Expired or invalid (will auto-refresh on next API call)"))}let{spinner:o}=(L(),_(Re));o.start("Testing connection...");try{let s=await i.getApplicationCredentials();if(!s){o.fail("No application credentials found");return}let{SinchClient:r}=require("@sinch/sdk-core");await new r({applicationKey:s.applicationKey,applicationSecret:s.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:s.applicationKey}),o.succeed("Connection active")}catch{o.fail("Connection failed"),console.log(g.default.yellow("\u26A0\uFE0F Credentials may be expired or invalid"))}}else console.log(g.default.red("\u274C Not authenticated")),console.log(g.default.gray('Run "sinch auth login" to authenticate'))}catch(e){console.error(g.default.red(`Failed to check status: ${e.message}`)),process.exit(1)}});Me.command("logout").description("Clear stored authentication credentials").action(async()=>{let{config:i}=(j(),_(Ce)),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 i.load(),await i.clearCredentials(),console.log(g.default.green("\u2705 Logged out successfully")),console.log(g.default.gray("All credentials cleared from secure storage"))):console.log(g.default.gray("Logout cancelled"))}catch(n){console.error(g.default.red(`Logout failed: ${n.message}`)),process.exit(1)}});te.addCommand(Me);te.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 i=>{let{config:e}=(j(),_(Ce));try{if(await e.load(),i.set){let[n,o]=i.set.split("=");(!n||!o)&&(console.error(g.default.red("Invalid format. Use: --set key=value")),process.exit(1)),e.set(n,o),await e.save(),console.log(g.default.green(`\u2705 Set ${n} = ${o}`))}else if(i.get){let n=e.get(i.get);console.log(n!==null?n:g.default.gray("(not set)"))}else if(i.list){console.log(g.default.blue(`
120
- \u{1F4CB} Configuration:`));let n=e.getApiConfig();Object.entries(n).forEach(([o,s])=>{console.log(` ${o}: ${s}`)})}else console.log(g.default.blue(`
127
+ `));let a=await n.prompt([{type:"input",name:"projectId",message:"Project ID (from Sinch Dashboard):",default:s?.projectId||void 0,validate:d=>!d&&s?.projectId?!0:d.length>0||"Project ID is required"},{type:"input",name:"keyId",message:"Key ID (from Project \u2192 Access Keys):",default:s?.keyId||void 0,validate:d=>!d&&s?.keyId?!0:d.length>0||"Key ID is required"},{type:"password",name:"keySecret",message:"Key Secret:",default:i?.keySecret||void 0,validate:d=>!d&&i?.keySecret?!0:d.length>0||"Key Secret is required"},{type:"input",name:"applicationKey",message:"Voice Application Key:",default:s?.applicationKey||void 0,validate:d=>!d&&s?.applicationKey?!0:d.length>0||"Application Key is required"},{type:"password",name:"applicationSecret",message:"Voice Application Secret:",default:i?.applicationSecret||void 0,validate:d=>!d&&i?.applicationSecret?!0:d.length>0||"Application Secret is required"}]),r={projectId:a.projectId||s?.projectId,keyId:a.keyId||s?.keyId,keySecret:a.keySecret||i?.keySecret,applicationKey:a.applicationKey||s?.applicationKey,applicationSecret:a.applicationSecret||i?.applicationSecret},{spinner:c}=(T(),M(xe));c.start("Verifying credentials...");try{c.update("Obtaining OAuth access token...");let{SinchAPI:d}=(K(),M(Fe)),u=await new d({apiUrl:e.get("apiUrl"),projectId:r.projectId||e.get("projectId"),credentials:e._credentials}).authenticateOAuth(r.keyId,r.keySecret);c.succeed("OAuth token obtained successfully!"),c.start("Testing Voice API connection...");let{SinchClient:h}=require("@sinch/sdk-core");await new h({applicationKey:r.applicationKey,applicationSecret:r.applicationSecret}).voice.applications.getCallbackURLs({applicationkey:r.applicationKey}),c.succeed("Credentials verified successfully!"),await e._credentials.storeOAuthToken(u),await e._credentials.store(r),console.log(g.default.green(`
128
+ \u2705 Authentication successful!`)),console.log(g.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(g.default.blue("\u{1F512} Security:")),console.log(g.default.gray(" \u2022 Secrets stored in OS credential manager (Windows/macOS/Linux)")),console.log(g.default.gray(" \u2022 Non-sensitive data in ~/.sinch/config.json"))}catch(d){c.fail("Authentication failed"),console.error(g.default.red(`
129
+ \u274C Error: ${d.message}`)),console.log(g.default.yellow(`
130
+ \u{1F4A1} Please check your credentials and try again`)),process.exit(1)}}catch(i){console.error(g.default.red(`Authentication failed: ${i.message}`)),process.exit(1)}});it.command("status").description("Show current authentication status").action(async()=>{let{config:o}=(D(),M(Pe));try{await o.load();let e=await o.hasCredentials(),n=o.getPublicCredentialInfo();if(console.log(g.default.blue(`
131
+ \u{1F510} Authentication Status`)),e&&n){console.log(g.default.green("\u2705 Authenticated")),console.log(` Project ID: ${n.projectId}`),console.log(` Key ID: ${n.keyId}`),console.log(` Application Key: ${n.applicationKey}`),console.log(g.default.gray(" (Secrets stored securely in OS keychain)"));try{let s=(K(),M(Fe)).default,a=o.getApiConfig();await new s(a).authenticate(),console.log(g.default.green(" OAuth Token: Valid"))}catch{console.log(g.default.yellow(" OAuth Token: Expired or invalid (will auto-refresh on next API call)"))}let{spinner:i}=(T(),M(xe));i.start("Testing connection...");try{let s=await o.getApplicationCredentials();if(!s){i.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}),i.succeed("Connection active")}catch{i.fail("Connection failed"),console.log(g.default.yellow("\u26A0\uFE0F Credentials may be expired or invalid"))}}else console.log(g.default.red("\u274C Not authenticated")),console.log(g.default.gray('Run "sinch auth login" to authenticate'))}catch(e){console.error(g.default.red(`Failed to check status: ${e.message}`)),process.exit(1)}});it.command("logout").description("Clear stored authentication credentials").action(async()=>{let{config:o}=(D(),M(Pe)),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(g.default.green("\u2705 Logged out successfully")),console.log(g.default.gray("All credentials cleared from secure storage"))):console.log(g.default.gray("Logout cancelled"))}catch(n){console.error(g.default.red(`Logout failed: ${n.message}`)),process.exit(1)}});Q.addCommand(it);Q.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}=(D(),M(Pe));try{if(await e.load(),o.set){let[n,i]=o.set.split("=");(!n||!i)&&(console.error(g.default.red("Invalid format. Use: --set key=value")),process.exit(1)),e.set(n,i),await e.save(),console.log(g.default.green(`\u2705 Set ${n} = ${i}`))}else if(o.get){let n=e.get(o.get);console.log(n!==null?n:g.default.gray("(not set)"))}else if(o.list){console.log(g.default.blue(`
132
+ \u{1F4CB} Configuration:`));let n=e.getApiConfig();Object.entries(n).forEach(([i,s])=>{console.log(` ${i}: ${s}`)})}else console.log(g.default.blue(`
121
133
  \u2699\uFE0F Configuration Management`)),console.log(g.default.gray(`Use "sinch config --help" for available options
122
- `))}catch(n){console.error(g.default.red(`Failed to manage config: ${n.message}`)),process.exit(1)}});te.command("health").description("Check API connection and health").action(async()=>{let{SinchAPI:i}=(U(),_(Ae)),{config:e}=(j(),_(Ce)),{spinner:n}=(L(),_(Re));try{await e.load();let o=new i(e.getApiConfig());n.start("Checking API health...");let s=await o.checkHealth();n.succeed("API is healthy"),console.log(g.default.blue(`
123
- \u{1F3E5} Health Status:`)),console.log(` Status: ${g.default.green(s.status)}`),console.log(` API URL: ${e.get("apiUrl")}`),console.log(` Project ID: ${e.get("projectId")}`)}catch(o){n.fail("API health check failed"),console.error(g.default.red(`
124
- \u274C ${o.message}`)),process.exit(1)}});te.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 i=>{let e=i.shell.toLowerCase();i.install&&e==="powershell"?await Ei():e==="powershell"?Ri():e==="bash"?ji():e==="zsh"?Ti():(console.error(g.default.red(`Unsupported shell: ${e}`)),console.log("Supported shells: powershell, bash, zsh"),process.exit(1))});process.on("uncaughtException",i=>{console.error(g.default.red(`
125
- \u{1F4A5} Uncaught Exception: ${i.message}`)),process.env.DEBUG&&console.error(i.stack),process.exit(1)});process.on("unhandledRejection",i=>{console.error(g.default.red(`
126
- \u{1F4A5} Unhandled Rejection: ${i}`)),process.env.DEBUG&&console.error(i),process.exit(1)});async function Pi(){let i=process.argv.slice(2),e=i[0],n=["auth","help","completion","--help","-h","--version","-V"],o=i.includes("--non-interactive");if(e&&!n.includes(e)&&!n.some(s=>i.includes(s))){let{config:s}=(j(),_(Ce));if(await s.load(),!await s.hasCredentials()){o&&(console.error(g.default.red(`
127
- \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 r=require("inquirer");console.log(g.default.yellow(`
134
+ `))}catch(n){console.error(g.default.red(`Failed to manage config: ${n.message}`)),process.exit(1)}});Q.command("health").description("Check API connection and health").action(async()=>{let{SinchAPI:o}=(K(),M(Fe)),{config:e}=(D(),M(Pe)),{spinner:n}=(T(),M(xe));try{await e.load();let i=new o(e.getApiConfig());n.start("Checking API health...");let s=await i.checkHealth();n.succeed("API is healthy"),console.log(g.default.blue(`
135
+ \u{1F3E5} Health Status:`)),console.log(` Status: ${g.default.green(s.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(g.default.red(`
136
+ \u274C ${i.message}`)),process.exit(1)}});Q.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 Rs():e==="powershell"?_s():e==="bash"?Ts():e==="zsh"?Ns():(console.error(g.default.red(`Unsupported shell: ${e}`)),console.log("Supported shells: powershell, bash, zsh"),process.exit(1))});process.on("uncaughtException",o=>{console.error(g.default.red(`
137
+ \u{1F4A5} Uncaught Exception: ${o.message}`)),process.env.DEBUG&&console.error(o.stack),process.exit(1)});process.on("unhandledRejection",o=>{console.error(g.default.red(`
138
+ \u{1F4A5} Unhandled Rejection: ${o}`)),process.env.DEBUG&&console.error(o),process.exit(1)});async function js(){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(s=>o.includes(s))){let{config:s}=(D(),M(Pe));if(await s.load(),!await s.hasCredentials()){i&&(console.error(g.default.red(`
139
+ \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 a=require("inquirer");console.log(g.default.yellow(`
128
140
  \u26A0\uFE0F Authentication Required`)),console.log(`You need to authenticate with Sinch to use the CLI.
129
- `);let{shouldLogin:a}=await r.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(`
141
+ `);let{shouldLogin:r}=await a.prompt([{type:"confirm",name:"shouldLogin",message:"Would you like to login now?",default:!0}]);r?process.argv.splice(2,process.argv.length-2,"auth","login"):(console.log(`
130
142
  You can authenticate anytime with:`),console.log(` ${g.default.cyan("sinch auth login")}
131
- `),process.exit(0))}}te.parse(process.argv),process.argv.slice(2).length||(console.log(g.default.blue.bold(`
143
+ `),process.exit(0))}}Q.parse(process.argv),process.argv.slice(2).length||(console.log(g.default.blue.bold(`
132
144
  \u{1F3AF} Sinch Functions CLI`)),console.log(g.default.gray(`Serverless function platform for voice applications
133
- `)),console.log("Quick start:"),console.log(` ${g.default.cyan("sinch auth login")} # Authenticate with Sinch Voice API`),console.log(` ${g.default.cyan("sinch templates list")} # Browse available templates`),console.log(` ${g.default.cyan("sinch functions init")} # Create a new function`),console.log(` ${g.default.cyan("sinch functions dev")} # Start local development`),console.log(` ${g.default.cyan("sinch voice callback-url")} # Update webhook URL for live testing`),console.log(` ${g.default.cyan("sinch functions deploy")} # Deploy to production`),console.log(` ${g.default.cyan("sinch functions status [id]")} # Check deployment status`),console.log(` ${g.default.cyan("sinch secrets list")} # Manage custom secrets`),console.log(""),te.help())}Pi().catch(i=>{console.error(g.default.red("Error:"),i.message),process.exit(1)});async function Ei(){let{spinner:i}=(L(),_(Re));try{i.start("Installing PowerShell completion...");let e=tt.default.join(Tt.default.homedir(),"Documents","PowerShell"),n=tt.default.join(e,"sinch-completion.ps1");await me.default.ensureDir(e),i.update("Creating completion script...");let o=Ai();await me.default.writeFile(n,o),i.update("Updating PowerShell profile...");let s=await Ii(),r="";await me.default.pathExists(s)&&(r=await me.default.readFile(s,"utf8"));let a='. "$env:USERPROFILE\\Documents\\PowerShell\\sinch-completion.ps1"';if(r.includes("sinch-completion.ps1"))i.info("PowerShell completion already installed"),console.log(g.default.blue(`
134
- \u2139\uFE0F Completion is already installed`)),console.log(g.default.gray("If tab completion isn't working, try restarting PowerShell"));else{let u=r+(r?`
145
+ `)),console.log("Quick start:"),console.log(` ${g.default.cyan("sinch auth login")} # Authenticate with Sinch Voice API`),console.log(` ${g.default.cyan("sinch templates list")} # Browse available templates`),console.log(` ${g.default.cyan("sinch functions init")} # Create a new function`),console.log(` ${g.default.cyan("sinch functions dev")} # Start local development`),console.log(` ${g.default.cyan("sinch voice callback-url")} # Update webhook URL for live testing`),console.log(` ${g.default.cyan("sinch functions deploy")} # Deploy to production`),console.log(` ${g.default.cyan("sinch functions status [id]")} # Check deployment status`),console.log(` ${g.default.cyan("sinch secrets list")} # Manage custom secrets`),console.log(""),Q.help())}js().catch(o=>{console.error(g.default.red("Error:"),o.message),process.exit(1)});async function Rs(){let{spinner:o}=(T(),M(xe));try{o.start("Installing PowerShell completion...");let e=gt.default.join(Yt.default.homedir(),"Documents","PowerShell"),n=gt.default.join(e,"sinch-completion.ps1");await Se.default.ensureDir(e),o.update("Creating completion script...");let i=Ds();await Se.default.writeFile(n,i),o.update("Updating PowerShell profile...");let s=await Os(),a="";await Se.default.pathExists(s)&&(a=await Se.default.readFile(s,"utf8"));let r='. "$env:USERPROFILE\\Documents\\PowerShell\\sinch-completion.ps1"';if(a.includes("sinch-completion.ps1"))o.info("PowerShell completion already installed"),console.log(g.default.blue(`
146
+ \u2139\uFE0F Completion is already installed`)),console.log(g.default.gray("If tab completion isn't working, try restarting PowerShell"));else{let c=a+(a?`
135
147
  `:"")+`# Sinch Functions CLI completion
136
- `+a+`
137
- `;await me.default.writeFile(s,u),i.succeed("PowerShell completion installed successfully!"),console.log(g.default.green(`
148
+ `+r+`
149
+ `;await Se.default.writeFile(s,c),o.succeed("PowerShell completion installed successfully!"),console.log(g.default.green(`
138
150
  \u2705 Installation Complete!`)),console.log(g.default.blue("\u{1F4C1} Files created:")),console.log(` ${g.default.gray(n)}`),console.log(` ${g.default.gray("Updated:")} ${s}`),console.log(g.default.yellow(`
139
151
  \u26A1 To activate completion:`)),console.log(" 1. Restart PowerShell, OR"),console.log(" 2. Run: "+g.default.cyan(". $PROFILE")),console.log(g.default.gray(`
140
- \u{1F4A1} Test with: sinch functions <TAB>`))}}catch(e){i.fail("Failed to install PowerShell completion"),console.error(g.default.red(`\u274C Error: ${e.message}`)),console.log(g.default.yellow(`
141
- \u{1F4A1} Try manual installation with: sinch completion`)),process.exit(1)}}async function Ii(){return new Promise(i=>{let e=n=>new Promise(o=>{let s=(0,io.spawn)(n,["-Command","$PROFILE"],{stdio:["ignore","pipe","pipe"]}),r="";s.stdout.on("data",a=>{r+=a.toString()}),s.on("close",a=>{o(a===0?{success:!0,path:r.trim(),version:n}:{success:!1})}),s.on("error",()=>{o({success:!1})})});e("pwsh").then(n=>{n.success&&n.path?(console.log(g.default.gray(` Detected PowerShell 7 profile: ${n.path}`)),i(n.path)):e("powershell").then(o=>{if(o.success&&o.path)console.log(g.default.gray(` Detected Windows PowerShell profile: ${o.path}`)),i(o.path);else{let s=tt.default.join(Tt.default.homedir(),"Documents","PowerShell","Microsoft.PowerShell_profile.ps1");console.log(g.default.gray(` Using fallback profile path: ${s}`)),i(s)}})})})}function Ai(){return`# PowerShell completion for Sinch Functions CLI
152
+ \u{1F4A1} Test with: sinch functions <TAB>`))}}catch(e){o.fail("Failed to install PowerShell completion"),console.error(g.default.red(`\u274C Error: ${e.message}`)),console.log(g.default.yellow(`
153
+ \u{1F4A1} Try manual installation with: sinch completion`)),process.exit(1)}}async function Os(){return new Promise(o=>{let e=n=>new Promise(i=>{let s=(0,Xo.spawn)(n,["-Command","$PROFILE"],{stdio:["ignore","pipe","pipe"]}),a="";s.stdout.on("data",r=>{a+=r.toString()}),s.on("close",r=>{i(r===0?{success:!0,path:a.trim(),version:n}:{success:!1})}),s.on("error",()=>{i({success:!1})})});e("pwsh").then(n=>{n.success&&n.path?(console.log(g.default.gray(` Detected PowerShell 7 profile: ${n.path}`)),o(n.path)):e("powershell").then(i=>{if(i.success&&i.path)console.log(g.default.gray(` Detected Windows PowerShell profile: ${i.path}`)),o(i.path);else{let s=gt.default.join(Yt.default.homedir(),"Documents","PowerShell","Microsoft.PowerShell_profile.ps1");console.log(g.default.gray(` Using fallback profile path: ${s}`)),o(s)}})})})}function Ds(){return`# PowerShell completion for Sinch Functions CLI
142
154
  # Auto-generated by 'sinch completion --install'
143
155
  # Compatible with both PowerShell 7 and Windows PowerShell 5.1
144
156
 
@@ -185,7 +197,7 @@ Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
185
197
  # Silently fail if there are any errors in completion
186
198
  # This prevents PowerShell startup errors
187
199
  }
188
- }`}function Ri(){let i=`
200
+ }`}function _s(){let o=`
189
201
  # PowerShell completion for Sinch Functions CLI
190
202
  Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
191
203
  param($wordToComplete, $commandAst, $cursorPosition)
@@ -236,7 +248,7 @@ Register-ArgumentCompleter -Native -CommandName sinch -ScriptBlock {
236
248
  #
237
249
  # To find your profile location, run: $PROFILE
238
250
  `;console.log(g.default.blue("\u{1F527} PowerShell Completion Script")),console.log(g.default.gray(`Copy and save this to your PowerShell profile:
239
- `)),console.log(i),console.log(g.default.yellow("Installation Instructions:")),console.log(g.default.green("\u{1F680} Easy way: ")+g.default.cyan("sinch completion --install")),console.log(g.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(g.default.cyan(' . "$env:USERPROFILE\\\\Documents\\\\PowerShell\\\\sinch-completion.ps1"')),console.log("3. Restart PowerShell or run: . $PROFILE")}function ji(){let i=`
251
+ `)),console.log(o),console.log(g.default.yellow("Installation Instructions:")),console.log(g.default.green("\u{1F680} Easy way: ")+g.default.cyan("sinch completion --install")),console.log(g.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(g.default.cyan(' . "$env:USERPROFILE\\\\Documents\\\\PowerShell\\\\sinch-completion.ps1"')),console.log("3. Restart PowerShell or run: . $PROFILE")}function Ts(){let o=`
240
252
  # Bash completion for Sinch Functions CLI
241
253
  _sinch_completion() {
242
254
  local cur prev commands
@@ -277,7 +289,7 @@ complete -F _sinch_completion sinch
277
289
 
278
290
  # To install: Add this to your ~/.bashrc or ~/.bash_profile
279
291
  `;console.log(g.default.blue("\u{1F527} Bash Completion Script")),console.log(g.default.gray(`Add this to your ~/.bashrc or ~/.bash_profile:
280
- `)),console.log(i)}function Ti(){let i=`
292
+ `)),console.log(o)}function Ns(){let o=`
281
293
  #compdef sinch
282
294
 
283
295
  _sinch() {
@@ -332,4 +344,4 @@ _sinch "$@"
332
344
  # To install: Save as _sinch in your zsh completions directory
333
345
  # Usually: /usr/local/share/zsh/site-functions/_sinch
334
346
  `;console.log(g.default.blue("\u{1F527} Zsh Completion Script")),console.log(g.default.gray(`Save this as _sinch in your zsh completions directory:
335
- `)),console.log(i)}
347
+ `)),console.log(o)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinch/cli",
3
- "version": "0.1.25-beta.0",
3
+ "version": "0.1.27-beta.0",
4
4
  "description": "Official Sinch CLI - Manage all Sinch products from your terminal",
5
5
  "main": "dist/index.js",
6
6
  "bin": {